From ef5551f3ec28a49635c9cfc9355ca0ec7b763bde Mon Sep 17 00:00:00 2001 From: Federico Hernandez Date: Wed, 24 Feb 2016 23:49:51 +0100 Subject: [PATCH 0001/1455] Bumped version number to 2.6.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e96e0a64b..6a17d09cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ include (CheckStructHasMember) set (HAVE_CMAKE true) project (task) -set (PROJECT_VERSION "2.5.1") +set (PROJECT_VERSION "2.6.0") OPTION (ENABLE_SYNC "Enable 'task sync' support" ON) From 2c8205317fda071b2033046c99abd916c6378712 Mon Sep 17 00:00:00 2001 From: Federico Hernandez Date: Thu, 25 Feb 2016 00:07:51 +0100 Subject: [PATCH 0002/1455] Bumped documentation to 2.6.0 --- ChangeLog | 6 ++++-- NEWS | 28 +++++++++------------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index bc2164ccb..a1ed000df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2.6.0 () - + +------ current release --------------------------- + 2.5.1 (2016-02-24) 8b4ae3b54b44dfbd00b96cdd6dceb8dfe7cc1ea0 - TD-104 Unrecognized taskwarrior file format @@ -108,8 +112,6 @@ - The 'run_all' script was not correctly using exit code 0 when all tests pass (thanks to Gordon Ball). ------- current release --------------------------- - 2.5.0 (2015-10-21) dd5968a61b1fab258b38879cfdbb7d67f1bcd550 - TW-20 Task edit loses annotation precision, causing journal updating code diff --git a/NEWS b/NEWS index 3aaa93582..448a6ed99 100644 --- a/NEWS +++ b/NEWS @@ -1,33 +1,23 @@ -New Features in Taskwarrior 2.5.1 +New Features in Taskwarrior 2.6.0 - - As a bug-fix, code cleanup and performance release, new features are - limited to only small tweaks. - - The 'help' command now takes a 'usage' argument, which displays only the - command usage. + - -New Commands in Taskwarrior 2.5.1 +New Commands in Taskwarrior 2.6.0 - - None. + - -New Configuration Options in Taskwarrior 2.5.1 +New Configuration Options in Taskwarrior 2.6.0 - - New 'relative' column format for 'date' type columns does what 'remaining' - and 'countdown' do, but in one format. + - -Newly Deprecated Features in Taskwarrior 2.5.1 +Newly Deprecated Features in Taskwarrior 2.6.0 - -Removed Features in 2.5.1 +Removed Features in 2.6.0 - - There is no longer a 16-color default configuration for some platforms, - making all platforms 256-color. - - The configuration setting 'burndown.bias' is no longer used. - - The algorithm used to estimate completion on the 'burndown' reports has - been replaced by something less icky. Estimates are now based on the net - completion rate after the peak number of pending tasks. - - The unused 'dom' and 'shell.prompt' configuration settings were removed. + - Known Issues From 79e29abddc976ee2ea3f6acc5aea2dc55ed26706 Mon Sep 17 00:00:00 2001 From: Federico Hernandez Date: Thu, 25 Feb 2016 00:17:09 +0100 Subject: [PATCH 0003/1455] Bumped ref page to 2.6.0 --- doc/ref/task-ref.pages | Bin 292624 -> 292640 bytes doc/ref/task-ref.pdf | Bin 131250 -> 131022 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/ref/task-ref.pages b/doc/ref/task-ref.pages index 249c66b92977cff936474acdae17b6d10b446e2c..0f9a7818f11c46a4a65fcc101bc1669b5f2c1d2c 100644 GIT binary patch delta 16628 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 N;7%=y4RFs2{eOyZK=l9s delta 16649 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 diff --git a/doc/ref/task-ref.pdf b/doc/ref/task-ref.pdf index 95152a96607be1530d14b018a34e50c0d6c2f396..0b72893562ddfac6ee729c957209a1b9438c47d0 100644 GIT binary patch delta 66446 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

Talk On Travel<\/a> has added a photo to the pool:<\/p>

\"View<\/a><\/p> ", - "published": "2008-12-04T12:43:03Z", - "author": "nobody@flickr.com (Talk On Travel)", - "author_id": "33112458@N08", - "tags": "spain dolphins tenerife canaries lagomera aqualand playadelasamericas junglepark losgigantos loscristines talkontravel" - } - ] -} - diff --git a/test/json/interop.json b/test/json/interop.json deleted file mode 100644 index 5d680f627..000000000 --- a/test/json/interop.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "ResultSet": { - "totalResultsAvailable": "1827221", - "totalResultsReturned": 2, - "firstResultPosition": 1, - "Result": [ - { - "Title": "potato jpg", - "Summary": "Kentang Si bungsu dari keluarga Solanum tuberosum L ini ternyata memiliki khasiat untuk mengurangi kerutan jerawat bintik hitam dan kemerahan pada kulit Gunakan seminggu sekali sebagai", - "Url": "http:\/\/www.mediaindonesia.com\/spaw\/uploads\/images\/potato.jpg", - "ClickUrl": "http:\/\/www.mediaindonesia.com\/spaw\/uploads\/images\/potato.jpg", - "RefererUrl": "http:\/\/www.mediaindonesia.com\/mediaperempuan\/index.php?ar_id=Nzkw", - "FileSize": 22630, - "FileFormat": "jpeg", - "Height": "362", - "Width": "532", - "Thumbnail": { - "Url": "http:\/\/thm-a01.yimg.com\/nimage\/557094559c18f16a", - "Height": "98", - "Width": "145" - } - }, - { - "Title": "potato jpg", - "Summary": "Introduction of puneri aloo This is a traditional potato preparation flavoured with curry leaves and peanuts and can be eaten on fasting day Preparation time 10 min", - "Url": "http:\/\/www.infovisual.info\/01\/photo\/potato.jpg", - "ClickUrl": "http:\/\/www.infovisual.info\/01\/photo\/potato.jpg", - "RefererUrl": "http:\/\/sundayfood.com\/puneri-aloo-indian-%20recipe", - "FileSize": 119398, - "FileFormat": "jpeg", - "Height": "685", - "Width": "1024", - "Thumbnail": { - "Url": "http:\/\/thm-a01.yimg.com\/nimage\/7fa23212efe84b64", - "Height": "107", - "Width": "160" - } - } - ] - } -} diff --git a/test/json/iphone.json b/test/json/iphone.json deleted file mode 100644 index 08dcdf40a..000000000 --- a/test/json/iphone.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "menu": { - "header": "xProgress SVG Viewer", - "items": [ - { - "id": "Open" - }, - { - "id": "OpenNew", - "label": "Open New" - }, - null, - { - "id": "ZoomIn", - "label": "Zoom In" - }, - { - "id": "ZoomOut", - "label": "Zoom Out" - }, - { - "id": "OriginalView", - "label": "Original View" - }, - null, - { - "id": "Quality" - }, - { - "id": "Pause" - }, - { - "id": "Mute" - }, - null, - { - "id": "Find", - "label": "Find..." - }, - { - "id": "FindAgain", - "label": "Find Again" - }, - { - "id": "Copy" - }, - { - "id": "CopyAgain", - "label": "Copy Again" - }, - { - "id": "CopySVG", - "label": "Copy SVG" - }, - { - "id": "ViewSVG", - "label": "View SVG" - }, - { - "id": "ViewSource", - "label": "View Source" - }, - { - "id": "SaveAs", - "label": "Save As" - }, - null, - { - "id": "Help" - }, - { - "id": "About", - "label": "About xProgress CVG Viewer..." - } - ] - } -} diff --git a/test/json/twitter.json b/test/json/twitter.json deleted file mode 100644 index bfbf99087..000000000 --- a/test/json/twitter.json +++ /dev/null @@ -1,50 +0,0 @@ -{"results":[ - - {"text":"@twitterapi http:\/\/tinyurl.com\/ctrefg", - - "to_user_id":396524, - - "to_user":"TwitterAPI", - - "from_user":"jkoum", - - "metadata": - - { - - "result_type":"popular", - - "recent_retweets": 109 - - }, - - "id":1478555574, - - "from_user_id":1833773, - - "iso_language_code":"nl", - - "source":"twitter<\/a>", - - "profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/118412707\/2522215727_a5f07da155_b_normal.jpg", - - "created_at":"Wed, 08 Apr 2009 19:22:10 +0000"} - - ], - - "since_id":0, - - "max_id":1480307926, - - "refresh_url":"?since_id=1480307926&q=%40twitterapi", - - "results_per_page":15, - - "next_page":"?page=2&max_id=1480307926&q=%40twitterapi", - - "completed_in":0.031704, - - "page":1, - - "query":"%40twitterapi" -} diff --git a/test/json/youtube.json b/test/json/youtube.json deleted file mode 100644 index 7e97ee6a8..000000000 --- a/test/json/youtube.json +++ /dev/null @@ -1,53 +0,0 @@ -{"apiVersion":"2.0", - "data":{ - "updated":"2010-01-07T19:58:42.949Z", - "totalItems":800, - "startIndex":1, - "itemsPerPage":1, - "items":[ - {"id":"hYB0mn5zh2c", - "uploaded":"2007-06-05T22:07:03.000Z", - "updated":"2010-01-07T13:26:50.000Z", - "uploader":"GoogleDeveloperDay", - "category":"News", - "title":"Google Developers Day US - Maps API Introduction", - "description":"Google Maps API Introduction ...", - "tags":[ - "GDD07","GDD07US","Maps" - ], - "thumbnail":{ - "default":"http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg", - "hqDefault":"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg" - }, - "player":{ - "default":"http://www.youtube.com/watch?v\u003dhYB0mn5zh2c" - }, - "content":{ - "1":"rtsp://v5.cache3.c.youtube.com/CiILENy.../0/0/0/video.3gp", - "5":"http://www.youtube.com/v/hYB0mn5zh2c?f...", - "6":"rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp" - }, - "duration":2840, - "aspectRatio":"widescreen", - "rating":4.63, - "ratingCount":68, - "viewCount":220101, - "favoriteCount":201, - "commentCount":22, - "status":{ - "value":"restricted", - "reason":"limitedSyndication" - }, - "accessControl":{ - "syndicate":"allowed", - "commentVote":"allowed", - "rate":"allowed", - "list":"allowed", - "comment":"allowed", - "embed":"allowed", - "videoRespond":"moderated" - } - } - ] - } -} diff --git a/test/json_test.cpp b/test/json_test.cpp deleted file mode 100644 index 0a1879b17..000000000 --- a/test/json_test.cpp +++ /dev/null @@ -1,87 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -Context context; - -//////////////////////////////////////////////////////////////////////////////// -int main (int argc, char** argv) -{ - if (argc == 1) - { - std::cout << "\nUsage: json_test [-q] ...\n" - << "\n" - << " -q quiet, no JSON dump\n" - << " file containing JSON\n" - << " JSON string, may need to be quoted\n" - << "\n"; - return 0; - } - - bool quiet = false; - for (int i = 1; i < argc; ++i) - if (!strcmp (argv[i], "-q")) - quiet = true; - - for (int i = 1; i < argc; ++i) - { - if (strcmp (argv[i], "-q")) - { - try - { - json::value* root; - File file (argv[i]); - if (file.exists ()) - { - std::string contents; - file.read (contents); - root = json::parse (contents); - } - else - root = json::parse (argv[i]); - - if (root && !quiet) - std::cout << root->dump () << "\n"; - - delete root; - } - - catch (const std::string& e) { std::cout << e << "\n"; } - catch (...) { std::cout << "Unknown error\n"; } - } - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/test/json_test.t b/test/json_test.t deleted file mode 100755 index a1f566b2f..000000000 --- a/test/json_test.t +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -############################################################################### -# -# Copyright 2006 - 2016, Paul Beckingham, Federico Hernandez. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# http://www.opensource.org/licenses/mit-license.php -# -############################################################################### - -import sys -import os -import unittest -from glob import glob -# Ensure python finds the local simpletap module -sys.path.append(os.path.dirname(os.path.abspath(__file__))) - -from basetest import TestCase -from basetest.utils import CURRENT_DIR, run_cmd_wait_nofail -from basetest.meta import MetaTest - - -class MetaTestJson(MetaTest): - """Helper metaclass to simplify test logic below (TestJson) - - Creates test_methods in the TestCase class dynamically named after the - arguments used. - """ - @staticmethod - def make_function(classname, *args, **kwargs): - filepath = args[0] - TEST_BIN = kwargs.get("TEST_BIN") - - def test(self): - # ### Body of the usual test_testcase ### # - cmd = (TEST_BIN, filepath) - code, out, err = run_cmd_wait_nofail(cmd) - - self.assertNotIn("Error", out) - - filename = os.path.basename(filepath) - - # Title of test in report - test.__doc__ = "{0} {1}".format(classname, filename) - - return test - - -class TestJsonParsing(TestCase): - __metaclass__ = MetaTestJson - - EXTRA = {} - EXTRA["TEST_DIR"] = os.path.abspath(os.path.join(CURRENT_DIR, "..")) - EXTRA["TEST_BIN"] = os.path.join(EXTRA["TEST_DIR"], "json_test") - - TESTS = ( - zip(glob(os.path.join(EXTRA["TEST_DIR"], "json/*.json"))) - ) - - -if __name__ == "__main__": - from simpletap import TAPTestRunner - unittest.main(testRunner=TAPTestRunner()) - -# vim: ai sts=4 et sw=4 ft=python From 058f9ab2181e4d405e8cbd374032924728de41c3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:48:21 -0400 Subject: [PATCH 0074/1455] Tests: Removed redundant format tests --- test/.gitignore | 1 - test/CMakeLists.txt | 2 +- test/i18n.t.cpp | 81 --------------------------------------------- 3 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 test/i18n.t.cpp diff --git a/test/.gitignore b/test/.gitignore index dd2709758..9aaaafcec 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -10,7 +10,6 @@ config.t dates.t eval.t fs.t -i18n.t iso8601d.t iso8601p.t lexer.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6a4d15834..b68ab046b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,7 +14,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) -set (test_SRCS autocomplete.t col.t color.t config.t fs.t i18n.t list.t +set (test_SRCS autocomplete.t col.t color.t config.t fs.t list.t msg.t nibbler.t t.t tdb2.t text.t utf8.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t diff --git a/test/i18n.t.cpp b/test/i18n.t.cpp deleted file mode 100644 index 8127c9dc8..000000000 --- a/test/i18n.t.cpp +++ /dev/null @@ -1,81 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -Context context; - -//////////////////////////////////////////////////////////////////////////////// -int main (int, char**) -{ - UnitTest t (11); - - // Ensure environment has no influence. - unsetenv ("TASKDATA"); - unsetenv ("TASKRC"); - - try - { - t.is (format ("pre {1} post", "mid"), "pre mid post", "format 1a"); - t.is (format ("pre {1}{1} post", "mid"), "pre midmid post", "format 1b"); - t.is (format ("pre {1} post", 0), "pre 0 post", "format 1c"); - t.is (format ("pre {1}{1} post", 0), "pre 00 post", "format 1d"); - - t.is (format ("pre {1}{2} post", "one", "two"), "pre onetwo post", "format 2a"); - t.is (format ("pre {2}{1} post", "one", "two"), "pre twoone post", "format 2b"); - t.is (format ("pre {1}{2} post", "one", 2), "pre one2 post", "format 2c"); - t.is (format ("pre {1}{2} post", 1, "two"), "pre 1two post", "format 2d"); - t.is (format ("pre {1}{2} post", 1, 2), "pre 12 post", "format 2e"); - - t.is (format ("pre {1}{2}{3} post", "one", "two", "three"), "pre onetwothree post", "format 3a"); - t.is (format ("pre {3}{1}{2} post", "one", "two", "three"), "pre threeonetwo post", "format 3b"); - } - - catch (const std::string& error) - { - t.diag (error); - return -1; - } - - catch (...) - { - t.diag ("Unknown error."); - return -2; - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// From 446580d8dd868c773d9ee1ffae3bc445fd631cd9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:50:14 -0400 Subject: [PATCH 0075/1455] Tests: Removed redundant listt tests --- test/.gitignore | 1 - test/CMakeLists.txt | 2 +- test/list.t.cpp | 76 --------------------------------------------- 3 files changed, 1 insertion(+), 78 deletions(-) delete mode 100644 test/list.t.cpp diff --git a/test/.gitignore b/test/.gitignore index 9aaaafcec..4ea817725 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -13,7 +13,6 @@ fs.t iso8601d.t iso8601p.t lexer.t -list.t msg.t nibbler.t t.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b68ab046b..d736af423 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,7 +14,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) -set (test_SRCS autocomplete.t col.t color.t config.t fs.t list.t +set (test_SRCS autocomplete.t col.t color.t config.t fs.t msg.t nibbler.t t.t tdb2.t text.t utf8.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t diff --git a/test/list.t.cpp b/test/list.t.cpp deleted file mode 100644 index 92c71d10a..000000000 --- a/test/list.t.cpp +++ /dev/null @@ -1,76 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -//////////////////////////////////////////////////////////////////////////////// -int main (int, char**) -{ - UnitTest t (8); - - // 1,2,3 <=> 2,3,4 - std::vector string_one {"1", "2", "3"}; - std::vector string_two {"2", "3", "4"}; - std::vector string_three {"2", "3", "4"}; - std::vector string_four; - - // What are the differences? - std::vector string_leftOnly; - std::vector string_rightOnly; - listDiff (string_one, string_two, string_leftOnly, string_rightOnly); - t.is ((int) string_leftOnly.size (), 1, "std::string (1,2,3) <=> (2,3,4) = 1<-"); - t.is (string_leftOnly[0], "1", "std::string (1,2,3) <=> (2,3,4) = 1<-"); - - t.is ((int) string_rightOnly.size (), 1, "std::string (1,2,3) <=> (2,3,4) = ->4"); - t.is (string_rightOnly[0], "4", "std::string (1,2,3) <=> (2,3,4) = ->4"); - - // Now do it all again, with integers. - - // 1,2,3 <=> 2,3,4 - std::vector int_one {1, 2, 3}; - std::vector int_two {2, 3, 4}; - std::vector int_three {2, 3, 4}; - std::vector int_four; - - // What are the differences? - std::vector int_leftOnly; - std::vector int_rightOnly; - listDiff (int_one, int_two, int_leftOnly, int_rightOnly); - t.is ((int) int_leftOnly.size (), 1, "int (1,2,3) <=> (2,3,4) = 1<-"); - t.is (int_leftOnly[0], "1", "int (1,2,3) <=> (2,3,4) = 1<-"); - - t.is ((int) int_rightOnly.size (), 1, "int (1,2,3) <=> (2,3,4) = ->4"); - t.is (int_rightOnly[0], "4", "int (1,2,3) <=> (2,3,4) = ->4"); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// - From 43de419cdd817bc38e9639132d51be15dcb3bdfc Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:52:20 -0400 Subject: [PATCH 0076/1455] libshared: Integrated utf8, wcwidth --- src/CMakeLists.txt | 8 +- src/utf8.cpp | 296 --------------------------------------------- src/utf8.h | 45 ------- src/wcwidth6.cpp | 211 -------------------------------- 4 files changed, 4 insertions(+), 556 deletions(-) delete mode 100644 src/utf8.cpp delete mode 100644 src/utf8.h delete mode 100644 src/wcwidth6.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 231508ba1..2638d2959 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,14 +35,14 @@ add_library (task CLI2.cpp CLI2.h rules.cpp sort.cpp text.cpp text.h - utf8.cpp utf8.h - util.cpp util.h - wcwidth6.cpp) + util.cpp util.h) add_library (libshared libshared/src/JSON.cpp libshared/src/JSON.h libshared/src/Pig.cpp libshared/src/Pig.h libshared/src/RX.cpp libshared/src/RX.h - libshared/src/unicode.cpp libshared/src/unicode.h) + libshared/src/unicode.cpp libshared/src/unicode.h + libshared/src/utf8.cpp libshared/src/utf8.h + libshared/src/wcwidth6.cpp) add_executable (task_executable main.cpp) add_executable (calc_executable calc.cpp) diff --git a/src/utf8.cpp b/src/utf8.cpp deleted file mode 100644 index 34b4fabf1..000000000 --- a/src/utf8.cpp +++ /dev/null @@ -1,296 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2013 - 2016, 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 - -//////////////////////////////////////////////////////////////////////////////// -// Converts '0' -> 0 -// '9' -> 9 -// 'a'/'A' -> 10 -// 'f'/'F' -> 15 -#define XDIGIT(x) ((x) >= '0' && (x) <= '9' ? ((x) - '0') : \ - (x) >= 'a' && (x) <= 'f' ? ((x) + 10 - 'a') : \ - (x) >= 'A' && (x) <= 'F' ? ((x) + 10 - 'A') : 0) - -//////////////////////////////////////////////////////////////////////////////// -// Note: Assumes 4-digit hex codepoints: -// xxxx -// \uxxxx -// U+xxxx -unsigned int utf8_codepoint (const std::string& input) -{ - unsigned int codepoint = 0; - int length = input.length (); - - // U+xxxx, \uxxxx - if (length >= 6 && - ((input[0] == 'U' && input[1] == '+') || - (input[0] == '\\' && input[1] == 'u'))) - { - codepoint = XDIGIT (input[2]) << 12 | - XDIGIT (input[3]) << 8 | - XDIGIT (input[4]) << 4 | - XDIGIT (input[5]); - } - else if (length >= 4) - { - codepoint = XDIGIT (input[0]) << 12 | - XDIGIT (input[1]) << 8 | - XDIGIT (input[2]) << 4 | - XDIGIT (input[3]); - } - - return codepoint; -} - -//////////////////////////////////////////////////////////////////////////////// -// Iterates along a UTF8 string. -// - argument i counts bytes advanced through the string -// - returns the next character -unsigned int utf8_next_char (const std::string& input, std::string::size_type& i) -{ - if (input[i] == '\0') - return 0; - - // How many bytes in the sequence? - int length = utf8_sequence (input[i]); - i += length; - - // 0xxxxxxx -> 0xxxxxxx - if (length == 1) - return input[i - 1]; - - // 110yyyyy 10xxxxxx -> 00000yyy yyxxxxxx - if (length == 2) - return ((input[i - 2] & 0x1F) << 6) + - (input[i - 1] & 0x3F); - - // 1110zzzz 10yyyyyy 10xxxxxx -> zzzzyyyy yyxxxxxx - if (length == 3) - return ((input[i - 3] & 0xF) << 12) + - ((input[i - 2] & 0x3F) << 6) + - (input[i - 1] & 0x3F); - - // 11110www 10zzzzzz 10yyyyyy 10xxxxxx -> 000wwwzz zzzzyyyy yyxxxxxx - if (length == 4) - return ((input[i - 4] & 0x7) << 18) + - ((input[i - 3] & 0x3F) << 12) + - ((input[i - 2] & 0x3F) << 6) + - (input[i - 1] & 0x3F); - - // Default: pretend as though it's a single character. - // TODO Or should this throw? - return input[i - 1]; -} - -//////////////////////////////////////////////////////////////////////////////// -// http://en.wikipedia.org/wiki/UTF-8 -std::string utf8_character (unsigned int codepoint) -{ - char sequence[5] {}; - - // 0xxxxxxx -> 0xxxxxxx - if (codepoint < 0x80) - { - sequence[0] = codepoint; - } - - // 00000yyy yyxxxxxx -> 110yyyyy 10xxxxxx - else if (codepoint < 0x800) - { - sequence[0] = 0xC0 | (codepoint & 0x7C0) >> 6; - sequence[1] = 0x80 | (codepoint & 0x3F); - } - - // zzzzyyyy yyxxxxxx -> 1110zzzz 10yyyyyy 10xxxxxx - else if (codepoint < 0x10000) - { - sequence[0] = 0xE0 | (codepoint & 0xF000) >> 12; - sequence[1] = 0x80 | (codepoint & 0xFC0) >> 6; - sequence[2] = 0x80 | (codepoint & 0x3F); - } - - // 000wwwzz zzzzyyyy yyxxxxxx -> 11110www 10zzzzzz 10yyyyyy 10xxxxxx - else if (codepoint < 0x110000) - { - sequence[0] = 0xF0 | (codepoint & 0x1C0000) >> 18; - sequence[1] = 0x80 | (codepoint & 0x03F000) >> 12; - sequence[2] = 0x80 | (codepoint & 0x0FC0) >> 6; - sequence[3] = 0x80 | (codepoint & 0x3F); - } - - return std::string (sequence); -} - -//////////////////////////////////////////////////////////////////////////////// -int utf8_sequence (unsigned int character) -{ - if ((character & 0xE0) == 0xC0) - return 2; - - if ((character & 0xF0) == 0xE0) - return 3; - - if ((character & 0xF8) == 0xF0) - return 4; - - return 1; -} - -//////////////////////////////////////////////////////////////////////////////// -// Length of a string in characters. -unsigned int utf8_length (const std::string& str) -{ - int byteLength = str.length (); - int charLength = byteLength; - const char* data = str.data (); - - // Decrement the number of bytes for each byte that matches 0b10?????? - // this way only the first byte of any utf8 sequence is counted. - for (int i = 0; i < byteLength; i++) - { - // Extract the first two bits and check whether they are 10 - if ((data[i] & 0xC0) == 0x80) - charLength--; - } - - return charLength; -} - -//////////////////////////////////////////////////////////////////////////////// -// Width of a string in character cells. -unsigned int utf8_width (const std::string& str) -{ - unsigned int length = 0; - std::string::size_type i = 0; - unsigned int c; - while ((c = utf8_next_char (str, i))) - { - // Control characters, and more especially newline characters, make - // mk_wcwidth() return -1. Ignore that, thereby "adding zero" to length. - // Since control characters are not displayed in reports, this is a valid - // choice. - int l = mk_wcwidth (c); - if (l != -1) - length += l; - } - - return length; -} - -//////////////////////////////////////////////////////////////////////////////// -unsigned int utf8_text_length (const std::string& str) -{ - int byteLength = str.length (); - int charLength = byteLength; - const char* data = str.data (); - bool in_color = false; - - // Decrement the number of bytes for each byte that matches 0b10?????? - // this way only the first byte of any utf8 sequence is counted. - for (int i = 0; i < byteLength; i++) - { - if (in_color) - { - if (data[i] == 'm') - in_color = false; - - --charLength; - } - else - { - if (data[i] == 033) - { - in_color = true; - --charLength; - } - else - { - // Extract the first two bits and check whether they are 10 - if ((data[i] & 0xC0) == 0x80) - --charLength; - } - } - } - - return charLength; -} - -//////////////////////////////////////////////////////////////////////////////// -unsigned int utf8_text_width (const std::string& str) -{ - bool in_color = false; - - unsigned int length = 0; - std::string::size_type i = 0; - unsigned int c; - while ((c = utf8_next_char (str, i))) - { - if (in_color) - { - if (c == 'm') - in_color = false; - } - else if (c == 033) - { - in_color = true; - } - else - length += mk_wcwidth (c); - } - - return length; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string utf8_substr ( - const std::string& input, - unsigned int start, - unsigned int length /* = 0 */) -{ - // Find the starting index. - std::string::size_type index_start = 0; - for (unsigned int i = 0; i < start; i++) - utf8_next_char (input, index_start); - - std::string result; - if (length) - { - std::string::size_type index_end = index_start; - for (unsigned int i = 0; i < length; i++) - utf8_next_char (input, index_end); - - result = input.substr (index_start, index_end - index_start); - } - else - result = input.substr (index_start); - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/utf8.h b/src/utf8.h deleted file mode 100644 index bf0a9e3c8..000000000 --- a/src/utf8.h +++ /dev/null @@ -1,45 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2013 - 2016, 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_UTF8 -#define INCLUDED_UTF8 - -#include - -unsigned int utf8_codepoint (const std::string&); -unsigned int utf8_next_char (const std::string&, std::string::size_type&); -std::string utf8_character (unsigned int); -int utf8_sequence (unsigned int); -unsigned int utf8_length (const std::string&); -unsigned int utf8_text_length (const std::string&); -unsigned int utf8_width (const std::string& str); -unsigned int utf8_text_width (const std::string&); -const std::string utf8_substr (const std::string&, unsigned int, unsigned int length = 0); - -int mk_wcwidth (wchar_t); - -#endif -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/wcwidth6.cpp b/src/wcwidth6.cpp deleted file mode 100644 index b26aa8f01..000000000 --- a/src/wcwidth6.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * This is an implementation of wcwidth() and wcswidth() (defined in - * IEEE Std 1002.1-2001) for Unicode. - * - * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html - * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html - * - * In fixed-width output devices, Latin characters all occupy a single - * "cell" position of equal width, whereas ideographic CJK characters - * occupy two such cells. Interoperability between terminal-line - * applications and (teletype-style) character terminals using the - * UTF-8 encoding requires agreement on which character should advance - * the cursor by how many cell positions. No established formal - * standards exist at present on which Unicode character shall occupy - * how many cell positions on character terminals. These routines are - * a first attempt of defining such behavior based on simple rules - * applied to data provided by the Unicode Consortium. - * - * For some graphical characters, the Unicode standard explicitly - * defines a character-cell width via the definition of the East Asian - * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes. - * In all these cases, there is no ambiguity about which width a - * terminal shall use. For characters in the East Asian Ambiguous (A) - * class, the width choice depends purely on a preference of backward - * compatibility with either historic CJK or Western practice. - * Choosing single-width for these characters is easy to justify as - * the appropriate long-term solution, as the CJK practice of - * displaying these characters as double-width comes from historic - * implementation simplicity (8-bit encoded characters were displayed - * single-width and 16-bit ones double-width, even for Greek, - * Cyrillic, etc.) and not any typographic considerations. - * - * Much less clear is the choice of width for the Not East Asian - * (Neutral) class. Existing practice does not dictate a width for any - * of these characters. It would nevertheless make sense - * typographically to allocate two character cells to characters such - * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be - * represented adequately with a single-width glyph. The following - * routines at present merely assign a single-cell width to all - * neutral characters, in the interest of simplicity. This is not - * entirely satisfactory and should be reconsidered before - * establishing a formal standard in this area. At the moment, the - * decision which Not East Asian (Neutral) characters should be - * represented by double-width glyphs cannot yet be answered by - * applying a simple rule from the Unicode database content. Setting - * up a proper standard for the behavior of UTF-8 character terminals - * will require a careful analysis not only of each Unicode character, - * but also of each presentation form, something the author of these - * routines has avoided to do so far. - * - * http://www.unicode.org/unicode/reports/tr11/ - * - * Markus Kuhn -- 2007-05-26 (Unicode 5.0) - * - * Permission to use, copy, modify, and distribute this software - * for any purpose and without fee is hereby granted. The author - * disclaims all warranties with regard to this software. - * - * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c - */ - -#include -#include - -struct interval { - int first; - int last; -}; - -/* auxiliary function for binary search in interval table */ -static int bisearch(wchar_t ucs, const struct interval *table, int max) { - int min = 0; - int mid; - - if (ucs < table[0].first || ucs > table[max].last) - return 0; - while (max >= min) { - mid = (min + max) / 2; - if (ucs > table[mid].last) - min = mid + 1; - else if (ucs < table[mid].first) - max = mid - 1; - else - return 1; - } - - return 0; -} - - -/* The following two functions define the column width of an ISO 10646 - * character as follows: - * - * - The null character (U+0000) has a column width of 0. - * - * - Other C0/C1 control characters and DEL will lead to a return - * value of -1. - * - * - Non-spacing and enclosing combining characters (general - * category code Mn or Me in the Unicode database) have a - * column width of 0. - * - * - SOFT HYPHEN (U+00AD) has a column width of 1. - * - * - Other format characters (general category code Cf in the Unicode - * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. - * - * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) - * have a column width of 0. - * - * - Spacing characters in the East Asian Wide (W) or East Asian - * Full-width (F) category as defined in Unicode Technical - * Report #11 have a column width of 2. - * - * - All remaining characters (including all printable - * ISO 8859-1 and WGL4 characters, Unicode control characters, - * etc.) have a column width of 1. - * - * This implementation assumes that wchar_t characters are encoded - * in ISO 10646. - */ - -int mk_wcwidth(wchar_t ucs) -{ - /* sorted list of non-overlapping intervals of non-spacing characters */ - /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ - static const struct interval combining[] = { - { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 }, - { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, - { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 }, - { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 }, - { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, - { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, - { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 }, - { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D }, - { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, - { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, - { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, - { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, - { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, - { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, - { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C }, - { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D }, - { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, - { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, - { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC }, - { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, - { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, - { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, - { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, - { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, - { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, - { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, - { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, - { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, - { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, - { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F }, - { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, - { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, - { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, - { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, - { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, - { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 }, - { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 }, - { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF }, - { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 }, - { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F }, - { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, - { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F }, - { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB }, - { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F }, - { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 }, - { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD }, - { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F }, - { 0xE0100, 0xE01EF } - }; - - /* test for 8-bit control characters */ - if (ucs == 0) - return 0; - if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) - return -1; - - /* binary search in table of non-spacing characters */ - if (bisearch(ucs, combining, - sizeof(combining) / sizeof(struct interval) - 1)) - return 0; - - /* if we arrive here, ucs is not a combining or C0/C1 control character */ - - return 1 + - (ucs >= 0x1100 && - (ucs <= 0x115f || /* Hangul Jamo init. consonants */ - ucs == 0x2329 || ucs == 0x232a || - (ucs >= 0x2e80 && ucs <= 0xa4cf && - ucs != 0x303f) || /* CJK ... Yi */ - (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ - (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ - (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ - (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ - (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ - (ucs >= 0xffe0 && ucs <= 0xffe6) -#ifndef CYGWIN - || - (ucs >= 0x20000 && ucs <= 0x2fffd) || - (ucs >= 0x30000 && ucs <= 0x3fffd) -#endif - ) - ); -} - From fb3563bf65b6470d5f1ca2e0a7e8ff19687cf53e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:54:18 -0400 Subject: [PATCH 0077/1455] Tests: Removed redundant utf8 tests --- test/.gitignore | 1 - test/CMakeLists.txt | 2 +- test/utf8.t.cpp | 98 --------------------------------------------- 3 files changed, 1 insertion(+), 100 deletions(-) delete mode 100644 test/utf8.t.cpp diff --git a/test/.gitignore b/test/.gitignore index 4ea817725..c01a7b026 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -20,7 +20,6 @@ taskmod.t tdb2.t text.t uri.t -utf8.t util.t variant_add.t variant_and.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d736af423..6514cd447 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,7 +15,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${TASK_INCLUDE_DIRS}) set (test_SRCS autocomplete.t col.t color.t config.t fs.t - msg.t nibbler.t t.t tdb2.t text.t utf8.t util.t view.t + msg.t nibbler.t t.t tdb2.t text.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t diff --git a/test/utf8.t.cpp b/test/utf8.t.cpp deleted file mode 100644 index 07bfdcb86..000000000 --- a/test/utf8.t.cpp +++ /dev/null @@ -1,98 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -//////////////////////////////////////////////////////////////////////////////// -int main (int, char**) -{ - UnitTest t (33); - - std::string ascii_text = "This is a test"; - std::string utf8_text = "más sábado miércoles"; - std::string utf8_wide_text = "改变各种颜色"; - - std::string ascii_text_color = "This is a test"; - std::string utf8_text_color = "más sábado miércoles"; - std::string utf8_wide_text_color = "改变各种颜色"; - - // unsigned int utf8_codepoint (const std::string&); - t.is ((int) utf8_codepoint ("\\u0020"), 32, "\\u0020 --> ' '"); - t.is ((int) utf8_codepoint ("U+0020"), 32, "U+0020 --> ' '"); - - // TODO unsigned int utf8_next_char (const std::string&, std::string::size_type&); - // TODO std::string utf8_character (unsigned int); - // TODO int utf8_sequence (unsigned int); - - // unsigned int utf8_length (const std::string&); - t.is ((int) utf8_length (ascii_text), 14, "ASCII utf8_length"); - t.is ((int) utf8_length (utf8_text), 20, "UTF8 utf8_length"); - t.is ((int) utf8_length (utf8_wide_text), 6, "UTF8 wide utf8_length"); - - // unsigned int utf8_width (const std::string&); - t.is ((int) utf8_width (ascii_text), 14, "ASCII utf8_width"); - t.is ((int) utf8_width (utf8_text), 20, "UTF8 utf8_width"); - t.is ((int) utf8_width (utf8_wide_text), 12, "UTF8 wide utf8_width"); - - // unsigned int utf8_text_length (const std::string&); - t.is ((int) utf8_text_length (ascii_text_color), 14, "ASCII utf8_text_length"); - t.is ((int) utf8_text_length (utf8_text_color), 20, "UTF8 utf8_text_length"); - t.is ((int) utf8_text_length (utf8_wide_text_color), 6, "UTF8 wide utf8_text_length"); - - // unsigned int utf8_text_width (const std::string&); - t.is ((int) utf8_text_width (ascii_text_color), 14, "ASCII utf8_text_width"); - t.is ((int) utf8_text_width (utf8_text_color), 20, "UTF8 utf8_text_width"); - t.is ((int) utf8_text_width (utf8_wide_text_color), 12, "UTF8 wide utf8_text_width"); - - // const std::string utf8_substr (const std::string&, unsigned int, unsigned int length = 0); - t.is (utf8_substr (ascii_text, 0, 2), "Th", "ASCII utf8_substr"); - t.is (utf8_substr (utf8_text, 0, 2), "má", "UTF8 utf8_substr"); - t.is (utf8_substr (utf8_wide_text, 0, 2), "改变", "UTF8 wide utf8_substr"); - - // int mk_wcwidth (wchar_t); - t.is (mk_wcwidth ('a'), 1, "mk_wcwidth U+0061 --> 1"); - t.is (mk_wcwidth (0x5149), 2, "mk_wcwidth U+5149 --> 2"); - t.is (mk_wcwidth (0x9a8c), 2, "mk_wcwidth U+9a8c --> 2"); - t.is (mk_wcwidth (0x4e70), 2, "mk_wcwidth U+4e70 --> 2"); - t.is (mk_wcwidth (0x94b1), 2, "mk_wcwidth U+94b1 --> 2"); - t.is (mk_wcwidth (0x5305), 2, "mk_wcwidth U+5305 --> 2"); - t.is (mk_wcwidth (0x91cd), 2, "mk_wcwidth U+91cd --> 2"); - t.is (mk_wcwidth (0x65b0), 2, "mk_wcwidth U+65b0 --> 2"); - t.is (mk_wcwidth (0x8bbe), 2, "mk_wcwidth U+8bbe --> 2"); - t.is (mk_wcwidth (0x8ba1), 2, "mk_wcwidth U+8ba1 --> 2"); - t.is (mk_wcwidth (0x5411), 2, "mk_wcwidth U+5411 --> 2"); - t.is (mk_wcwidth (0x4e0a), 2, "mk_wcwidth U+4e0a --> 2"); - t.is (mk_wcwidth (0x4e0b), 2, "mk_wcwidth U+4e0b --> 2"); - t.is (mk_wcwidth (0x7bad), 2, "mk_wcwidth U+7bad --> 2"); - t.is (mk_wcwidth (0x5934), 2, "mk_wcwidth U+5934 --> 2"); - t.is (mk_wcwidth (0xff0c), 2, "mk_wcwidth U+ff0c --> 2"); // comma - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// From 143e149de5c4ea8557d97aea0e22c174e501ac40 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 18:09:36 -0400 Subject: [PATCH 0078/1455] libshared: Added Table --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2638d2959..fbbd676aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,7 @@ add_library (task CLI2.cpp CLI2.h add_library (libshared libshared/src/JSON.cpp libshared/src/JSON.h libshared/src/Pig.cpp libshared/src/Pig.h libshared/src/RX.cpp libshared/src/RX.h + libshared/src/Table.cpp libshared/src/Table.h libshared/src/unicode.cpp libshared/src/unicode.h libshared/src/utf8.cpp libshared/src/utf8.h libshared/src/wcwidth6.cpp) From befab82c043ed0935922263c074587dbbf257cf6 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 18:16:34 -0400 Subject: [PATCH 0079/1455] DOM: Eiminated Nibbler --- src/DOM.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/DOM.cpp b/src/DOM.cpp index f938412c2..43fd96233 100644 --- a/src/DOM.cpp +++ b/src/DOM.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -60,7 +59,6 @@ bool getDOM (const std::string& name, Variant& value) return false; auto len = name.length (); - Nibbler n (name); // rc. --> context.config if (len > 3 && From d648e0ae44756d6c6ef9437de78ef401fa11a238 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 26 Jun 2016 09:15:08 -0400 Subject: [PATCH 0080/1455] libshared: Integrated FS --- src/CMakeLists.txt | 4 +- src/FS.cpp | 974 --------------------------------------------- src/FS.h | 145 ------- 3 files changed, 2 insertions(+), 1121 deletions(-) delete mode 100644 src/FS.cpp delete mode 100644 src/FS.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fbbd676aa..8170b9c17 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,7 +14,6 @@ add_library (task CLI2.cpp CLI2.h Dates.cpp Dates.h Eval.cpp Eval.h Filter.cpp Filter.h - FS.cpp FS.h Hooks.cpp Hooks.h ISO8601.cpp ISO8601.h Lexer.cpp Lexer.h @@ -37,7 +36,8 @@ add_library (task CLI2.cpp CLI2.h text.cpp text.h util.cpp util.h) -add_library (libshared libshared/src/JSON.cpp libshared/src/JSON.h +add_library (libshared libshared/src/FS.cpp libshared/src/FS.h + libshared/src/JSON.cpp libshared/src/JSON.h libshared/src/Pig.cpp libshared/src/Pig.h libshared/src/RX.cpp libshared/src/RX.h libshared/src/Table.cpp libshared/src/Table.h diff --git a/src/FS.cpp b/src/FS.cpp deleted file mode 100644 index 72bb9c72d..000000000 --- a/src/FS.cpp +++ /dev/null @@ -1,974 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -#if defined __APPLE__ -#include -#endif - -// Fixes build with musl libc. -#ifndef GLOB_TILDE -#define GLOB_TILDE 0 -#endif - -#ifndef GLOB_BRACE -#define GLOB_BRACE 0 -#endif - -//////////////////////////////////////////////////////////////////////////////// -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::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) -{ - auto expanded = expand (new_name); - if (_data != expanded) - { - if (std::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 == nullptr) - { - 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 (1); - } - 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, nullptr, &g)) -#else - if (!::glob (pattern.c_str (), GLOB_ERR | GLOB_BRACE | GLOB_TILDE, nullptr, &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 (nullptr) -, _h (-1) -, _locked (false) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -File::File (const Path& other) -: Path::Path (other) -, _fh (nullptr) -, _h (-1) -, _locked (false) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -File::File (const File& other) -: Path::Path (other) -, _fh (nullptr) -, _h (-1) -, _locked (false) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -File::File (const std::string& in) -: Path::Path (in) -, _fh (nullptr) -, _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; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string File::removeBOM (const std::string& input) -{ - if (input[0] && input[0] == '\xEF' && - input[1] && input[1] == '\xBB' && - input[2] && input[2] == '\xBF') - return input.substr (3); - - return input; -} - -//////////////////////////////////////////////////////////////////////////////// -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; -} - -//////////////////////////////////////////////////////////////////////////////// -void File::close () -{ - if (_fh) - { - if (_locked) - unlock (); - - fclose (_fh); - _fh = nullptr; - _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 ()) - { - bool first = true; - std::string line; - line.reserve (512 * 1024); - while (getline (in, line)) - { - // Detect forbidden BOM on first line. - if (first) - { - line = File::removeBOM (line); - first = false; - } - - 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 ()) - { - bool first = true; - std::string line; - line.reserve (512 * 1024); - while (getline (in, line)) - { - // Detect forbidden BOM on first line. - if (first) - { - line = File::removeBOM (line); - first = false; - } - - contents.push_back (line); - } - - in.close (); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// 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.c_str (), _fh); - } -} - -//////////////////////////////////////////////////////////////////////////////// -void File::write_raw (const std::string& line) -{ - if (!_fh) - open (); - - if (_fh) - fputs (line.c_str (), _fh); -} - -//////////////////////////////////////////////////////////////////////////////// -void File::truncate () -{ - if (!_fh) - open (); - - if (_fh) - if (ftruncate (_h, 0)) - throw format (STRING_FILE_TRUNCATE, errno, strerror (errno)); -} - -//////////////////////////////////////////////////////////////////////////////// -// 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; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::read (const std::string& name, std::string& contents) -{ - contents = ""; - - std::ifstream in (name.c_str ()); - if (in.good ()) - { - bool first = true; - std::string line; - line.reserve (1024); - while (getline (in, line)) - { - // Detect forbidden BOM on first line. - if (first) - { - line = File::removeBOM (line); - first = false; - } - - 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 ()) - { - bool first = true; - std::string line; - line.reserve (1024); - while (getline (in, line)) - { - // Detect forbidden BOM on first line. - if (first) - { - line = File::removeBOM (line); - first = false; - } - - 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::remove (const std::string& name) -{ - return unlink (expand (name).c_str ()) == 0 ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::copy (const std::string& from, const std::string& to) -{ - // 'from' must exist. - if (! access (from.c_str (), F_OK)) - { - std::ifstream src (from, std::ios::binary); - std::ofstream dst (to, std::ios::binary); - - dst << src.rdbuf (); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::move (const std::string& from, const std::string& to) -{ - auto expanded = expand (to); - if (from != expanded) - if (std::rename (from.c_str (), to.c_str ()) == 0) - return true; - - return 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::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 != nullptr) - { - struct dirent* de; - while ((de = readdir (dp)) != nullptr) - { - 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 == nullptr) - 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 != nullptr) - { - struct dirent* de; - while ((de = readdir (dp)) != nullptr) - { - 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 --git a/src/FS.h b/src/FS.h deleted file mode 100644 index 3d14800e1..000000000 --- a/src/FS.h +++ /dev/null @@ -1,145 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 (); - explicit Path (const Path&); - Path (const std::string&); - - 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 (); - explicit File (const Path&); - explicit 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 (); - void close (); - - bool lock (); - void unlock (); - - void read (std::string&); - void read (std::vector &); - - void append (const std::string&); - void append (const std::vector &); - void write_raw (const std::string&); - - 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 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 remove (const std::string&); - static bool copy (const std::string&, const std::string&); - static bool move (const std::string&, const std::string&); - static std::string removeBOM (const std::string&); - -private: - FILE* _fh; - int _h; - bool _locked; -}; - -class Directory : public File -{ -public: - Directory (); - explicit Directory (const Directory&); - explicit Directory (const File&); - explicit Directory (const Path&); - Directory (const std::string&); - - 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 From 62d25144250873a369c15ef26c3cd6e0d4ce0b6f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 26 Jun 2016 09:21:55 -0400 Subject: [PATCH 0081/1455] Tests: Removed redundant FS tests --- test/.gitignore | 1 - test/CMakeLists.txt | 2 +- test/fs.t.cpp | 311 -------------------------------------------- 3 files changed, 1 insertion(+), 313 deletions(-) delete mode 100644 test/fs.t.cpp diff --git a/test/.gitignore b/test/.gitignore index c01a7b026..b7c6be1a1 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -9,7 +9,6 @@ color.t config.t dates.t eval.t -fs.t iso8601d.t iso8601p.t lexer.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6514cd447..daf1442c0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,7 +14,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) -set (test_SRCS autocomplete.t col.t color.t config.t fs.t +set (test_SRCS autocomplete.t col.t color.t config.t msg.t nibbler.t t.t tdb2.t text.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t diff --git a/test/fs.t.cpp b/test/fs.t.cpp deleted file mode 100644 index 2a573c545..000000000 --- a/test/fs.t.cpp +++ /dev/null @@ -1,311 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -Context context; - -int main (int, char**) -{ - UnitTest t (116); - - // Ensure environment has no influence. - unsetenv ("TASKDATA"); - unsetenv ("TASKRC"); - - // Path (); - Path p0; - t.is (p0._data, "", "Path::Path"); - - // Path (const Path&); - Path p1 = Path ("foo"); - t.is (p1._data, Directory::cwd () + "/foo", "Path::operator="); - - // Path (const std::string&); - Path p2 ("~"); - t.ok (p2._data != "~", "~ expanded to " + p2._data); - - Path p3 ("/tmp"); - t.ok (p3._data == "/tmp", "/tmp -> /tmp"); - - // operator== - t.notok (p2 == p3, "p2 != p3"); - - // Path& operator= (const Path&); - Path p3_copy (p3); - t.is (p3._data, p3_copy._data, "Path::Path (Path&)"); - - // operator (std::string) const; - t.is ((std::string) p3, "/tmp", "Path::operator (std::string) const"); - - // std::string name () const; - Path p4 ("/a/b/c/file.ext"); - t.is (p4.name (), "file.ext", "/a/b/c/file.ext name is file.ext"); - - // std::string parent () const; - t.is (p4.parent (), "/a/b/c", "/a/b/c/file.ext parent is /a/b/c"); - - // std::string extension () const; - t.is (p4.extension (), "ext", "/a/b/c/file.ext extension is ext"); - - // bool exists () const; - t.ok (p2.exists (), "~ exists"); - t.ok (p3.exists (), "/tmp exists"); - - // bool is_directory () const; - t.ok (p2.is_directory (), "~ is_directory"); - t.ok (p3.is_directory (), "/tmp is_directory"); - - // bool is_link () const; - t.notok (p2.is_link (), "~ !is_link"); - - // bool readable () const; - t.ok (p2.readable (), "~ readable"); - t.ok (p3.readable (), "/tmp readable"); - - // bool writable () const; - t.ok (p2.writable (), "~ writable"); - t.ok (p3.writable (), "/tmp writable"); - - // bool executable () const; - t.ok (p2.executable (), "~ executable"); - t.ok (p3.executable (), "/tmp executable"); - - // static std::string expand (const std::string&); - t.ok (Path::expand ("~") != "~", "Path::expand ~ != ~"); - t.ok (Path::expand ("~/") != "~/", "Path::expand ~/ != ~/"); - - // static std::vector glob (const std::string&); - std::vector out = Path::glob ("/tmp"); - t.ok (out.size () == 1, "/tmp -> 1 result"); - t.is (out[0], "/tmp", "/tmp -> /tmp"); - - out = Path::glob ("/t?p"); - t.ok (out.size () == 1, "/t?p -> 1 result"); - t.is (out[0], "/tmp", "/t?p -> /tmp"); - - out = Path::glob ("/[s-u]mp"); - t.ok (out.size () == 1, "/[s-u]mp -> 1 result"); - t.is (out[0], "/tmp", "/[s-u]mp -> /tmp"); - - // bool is_absolute () const; - t.notok (p0.is_absolute (), "'' !is_absolute"); - t.ok (p1.is_absolute (), "foo is_absolute"); - t.ok (p2.is_absolute (), "~ is_absolute (after expansion)"); - t.ok (p3.is_absolute (), "/tmp is_absolute"); - t.ok (p4.is_absolute (), "/a/b/c/file.ext is_absolute"); - - Path p5 ("~/file.ext"); - t.notok (p5.name () == "~/file.ext", "~/file.ext --> ! ~/file.ext"); - - Directory tmp ("tmp"); - tmp.create (); - t.ok (tmp.exists (), "tmp dir created."); - - File::write ("tmp/file.t.txt", "This is a test\n"); - File f6 ("tmp/file.t.txt"); - t.ok (f6.size () == 15, "File::size tmp/file.t.txt good"); - t.ok (f6.mode () & S_IRUSR, "File::mode tmp/file.t.txt good"); - t.ok (File::remove ("tmp/file.t.txt"), "File::remove tmp/file.t.txt good"); - - // operator (std::string) const; - t.is ((std::string) f6, Directory::cwd () + "/tmp/file.t.txt", "File::operator (std::string) const"); - - t.ok (File::create ("tmp/file.t.create"), "File::create tmp/file.t.create good"); - t.ok (File::remove ("tmp/file.t.create"), "File::remove tmp/file.t.create good"); - - // basename (std::string) const; - t.is (f6.name (), "file.t.txt", "File::basename tmp/file.t.txt --> file.t.txt"); - - // dirname (std::string) const; - t.is (f6.parent (), Directory::cwd () + "/tmp", "File::dirname tmp/file.t.txt --> tmp"); - - // bool rename (const std::string&); - File f7 ("tmp/file.t.2.txt"); - f7.append ("something\n"); - f7.close (); - - t.ok (f7.rename ("tmp/file.t.3.txt"), "File::rename did not fail"); - t.is (f7._data, Directory::cwd () + "/tmp/file.t.3.txt", "File::rename stored new name"); - t.ok (f7.exists (), "File::rename new file exists"); - t.ok (f7.remove (), "File::remove tmp/file.t.3.txt good"); - t.notok (f7.exists (), "File::remove new file no longer exists"); - - // Test permissions. - File f8 ("tmp/file.t.perm.txt"); - f8.create (0744); - t.ok (f8.exists (), "File::create perm file exists"); - mode_t m = f8.mode (); - t.ok (m & S_IFREG, "File::mode tmp/file.t.perm.txt S_IFREG good"); - t.ok (m & S_IRUSR, "File::mode tmp/file.t.perm.txt r-------- good"); - t.ok (m & S_IWUSR, "File::mode tmp/file.t.perm.txt -w------- good"); - t.ok (m & S_IXUSR, "File::mode tmp/file.t.perm.txt --x------ good"); - t.ok (m & S_IRGRP, "File::mode tmp/file.t.perm.txt ---r----- good"); - t.notok (m & S_IWGRP, "File::mode tmp/file.t.perm.txt ----w---- good"); - t.notok (m & S_IXGRP, "File::mode tmp/file.t.perm.txt -----x--- good"); - t.ok (m & S_IROTH, "File::mode tmp/file.t.perm.txt ------r-- good"); - t.notok (m & S_IWOTH, "File::mode tmp/file.t.perm.txt -------w- good"); - t.notok (m & S_IXOTH, "File::mode tmp/file.t.perm.txt --------x good"); - f8.remove (); - t.notok (f8.exists (), "File::remove perm file no longer exists"); - - tmp.remove (); - t.notok (tmp.exists (), "tmp dir removed."); - tmp.create (); - t.ok (tmp.exists (), "tmp dir created."); - - // Directory (const File&); - // Directory (const Path&); - Directory d0 (Path ("tmp")); - Directory d1 (File ("tmp")); - Directory d2 (File (Path ("tmp"))); - t.is (d0._data, d1._data, "Directory(std::string) == Directory (File&)"); - t.is (d0._data, d2._data, "Directory(std::string) == Directory (File (Path &))"); - t.is (d1._data, d2._data, "Directory(File&)) == Directory (File (Path &))"); - - // Directory (const Directory&); - Directory d3 (d2); - t.is (d3._data, Directory::cwd () + "/tmp", "Directory (Directory&)"); - - // Directory (const std::string&); - Directory d4 ("tmp/test_directory"); - - // Directory& operator= (const Directory&); - Directory d5 = d4; - t.is (d5._data, Directory::cwd () + "/tmp/test_directory", "Directory::operator="); - - // operator (std::string) const; - t.is ((std::string) d3, Directory::cwd () + "/tmp", "Directory::operator (std::string) const"); - - // virtual bool create (); - t.ok (d5.create (), "Directory::create tmp/test_directory"); - t.ok (d5.exists (), "Directory::exists tmp/test_directory"); - - Directory d6 (d5._data + "/dir"); - t.ok (d6.create (), "Directory::create tmp/test_directory/dir"); - - File::create (d5._data + "/f0"); - File::create (d6._data + "/f1"); - - // std::vector list (); - std::vector files = d5.list (); - std::sort (files.begin (), files.end ()); - t.is ((int)files.size (), 2, "Directory::list 1 file"); - t.is (files[0], Directory::cwd () + "/tmp/test_directory/dir", "file[0] is tmp/test_directory/dir"); - t.is (files[1], Directory::cwd () + "/tmp/test_directory/f0", "file[1] is tmp/test_directory/f0"); - - // std::vector listRecursive (); - files = d5.listRecursive (); - std::sort (files.begin (), files.end ()); - t.is ((int)files.size (), 2, "Directory::list 1 file"); - t.is (files[0], Directory::cwd () + "/tmp/test_directory/dir/f1", "file is tmp/test_directory/dir/f1"); - t.is (files[1], Directory::cwd () + "/tmp/test_directory/f0", "file is tmp/test_directory/f0"); - - // virtual bool remove (); - t.ok (File::remove (d5._data + "/f0"), "File::remove tmp/test_directory/f0"); - t.ok (File::remove (d6._data + "/f1"), "File::remove tmp/test_directory/dir/f1"); - - t.ok (d6.remove (), "Directory::remove tmp/test_directory/dir"); - t.notok (d6.exists (), "Directory::exists tmp/test_directory/dir - no"); - - t.ok (d5.remove (), "Directory::remove tmp/test_directory"); - t.notok (d5.exists (), "Directory::exists tmp/test_directory - no"); - - // bool remove (const std::string&); - Directory d7 ("tmp/to_be_removed"); - t.ok (d7.create (), "Directory::create tmp/to_be_removed"); - File::create (d7._data + "/f0"); - Directory d8 (d7._data + "/another"); - t.ok (d8.create (), "Directory::create tmp/to_be_removed/another"); - File::create (d8._data + "/f1"); - t.ok (d7.remove (), "Directory::remove tmp/to_be_removed"); - t.notok (d7.exists (), "Directory tmp/to_be_removed gone"); - - // static std::string cwd (); - std::string cwd = Directory::cwd (); - t.ok (cwd.length () > 0, "Directory::cwd returned a value"); - - // bool parent (std::string&) const; - Directory d9 ("/one/two/three/four.txt"); - t.ok (d9.up (), "parent /one/two/three/four.txt --> true"); - t.is (d9._data, "/one/two/three", "parent /one/two/three/four.txt --> /one/two/three"); - t.ok (d9.up (), "parent /one/two/three --> true"); - t.is (d9._data, "/one/two", "parent /one/two/three --> /one/two"); - t.ok (d9.up (), "parent /one/two --> true"); - t.is (d9._data, "/one", "parent /one/two --> /one"); - t.ok (d9.up (), "parent /one --> true"); - t.is (d9._data, "/", "parent /one --> /"); - t.notok (d9.up (), "parent / --> false"); - - // Test permissions. - umask (0022); - Directory d10 ("tmp/dir.perm"); - d10.create (0750); - t.ok (d10.exists (), "Directory::create perm file exists"); - m = d10.mode (); - t.ok (m & S_IFDIR, "Directory::mode tmp/dir.perm S_IFDIR good"); - t.ok (m & S_IRUSR, "Directory::mode tmp/dir.perm r-------- good"); - t.ok (m & S_IWUSR, "Directory::mode tmp/dir.perm -w------- good"); - t.ok (m & S_IXUSR, "Directory::mode tmp/dir.perm --x------ good"); - t.ok (m & S_IRGRP, "Directory::mode tmp/dir.perm ---r----- good"); - t.notok (m & S_IWGRP, "Directory::mode tmp/dir.perm ----w---- good"); - t.ok (m & S_IXGRP, "Directory::mode tmp/dir.perm -----x--- good"); - t.notok (m & S_IROTH, "Directory::mode tmp/dir.perm ------r-- good"); - t.notok (m & S_IWOTH, "Directory::mode tmp/dir.perm -------w- good"); - t.notok (m & S_IXOTH, "Directory::mode tmp/dir.perm --------x good"); - d10.remove (); - t.notok (d10.exists (), "Directory::remove temp/dir.perm file no longer exists"); - - // Directory::cd - Directory d11 ("/tmp"); - t.ok (d11.cd (), "Directory::cd /tmp good"); - - tmp.remove (); - t.notok (tmp.exists (), "tmp dir removed."); - - // File::removeBOM - std::string line = "Should not be modified."; - t.is (File::removeBOM (line), line, "File::removeBOM 'Should not be modified' --> 'Should not be modified'"); - - line = "no"; - t.is (File::removeBOM (line), line, "File::removeBOM 'no' --> 'no'"); - - line = ""; - t.is (File::removeBOM (line), line, "File::removeBOM '' --> ''"); - - line = {'\xEF', '\xBB', '\xBF', 'F', 'o', 'o'}; - t.is (File::removeBOM (line), "Foo", "File::removeBOM 'Foo' --> 'Foo'"); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// From 4b62bf816c17c4ebc70608870a9946ca5966895f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 8 Jul 2016 23:09:17 -0400 Subject: [PATCH 0082/1455] Docs: ChangeLog had wrong bug id --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b22ccf462..8963df8f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,7 +16,7 @@ pending tasks. - TW-1795 Calendar underline on Day padding (thanks to Renato Alves). -- TW-1806 project:ide is not allowed +- TW-1805 project:ide is not allowed (thanks to Slaven ʙanovic). - TW-1807 dateformat lacks a flag to display day of week (thanks to Ellington Santos). From 661ce5888fe9ec71720840cd171909db3bbcd813 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 2 Aug 2016 14:48:50 +0300 Subject: [PATCH 0083/1455] Scripts: Quoted regular expression to avoid bash glob expansion The quote is needed, otherwise it is treated as a bash glob first, which causes trouble if there actually happens to be matching files, and fails entirely if `shopt -s failglob` is set. --- scripts/bash/task.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bash/task.sh b/scripts/bash/task.sh index e0c7fb039..ecb4fd528 100644 --- a/scripts/bash/task.sh +++ b/scripts/bash/task.sh @@ -72,7 +72,7 @@ _task_offer_contexts() { COMPREPLY=( $(compgen -W "$($taskcommand _context) define delete list none show" -- $cur) ) } -_task_context_alias=$($taskcommand show | grep alias.*context | cut -d' ' -f1 | cut -d. -f2) +_task_context_alias=$($taskcommand show | grep 'alias.*context' | cut -d' ' -f1 | cut -d. -f2) _task() { From e0f5943b6338833444ab0cce2c6ded8ea4cafb10 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 2 Aug 2016 08:25:02 -0400 Subject: [PATCH 0084/1455] Docs: Added Ran Benita --- AUTHORS | 1 + ChangeLog | 2 ++ 2 files changed, 3 insertions(+) diff --git a/AUTHORS b/AUTHORS index 93f150806..8681889f3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -130,6 +130,7 @@ The following submitted code, packages or analysis, and deserve special thanks: Tom Sydney Kerckhove Lynoure Braakman Sebastien Badia + Ran Benita Thanks to the following, who submitted detailed bug reports and excellent suggestions: diff --git a/ChangeLog b/ChangeLog index 8963df8f8..ca06056bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -36,6 +36,8 @@ - Correct a false-positive warning when a due date is removed and a wait is added. - Added 'QUARTER' virtual tag. +- Fixed unquoted glob in bash completion script + (thanks to Ran Benita). ------ current release --------------------------- From 394b7174cf1264aa89484f7077c9bf22b221a264 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 22 Aug 2016 09:19:18 -0400 Subject: [PATCH 0085/1455] L10N: Updated error message to not refer to only pending tasks --- src/l10n/eng-USA.h | 2 +- src/l10n/fra-FRA.h | 2 +- src/l10n/ita-ITA.h | 2 +- src/l10n/jpn-JPN.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 29575dad4..3a64918ba 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -480,7 +480,7 @@ #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}'" #define STRING_CMD_SYNC_NO_TLS "Taskwarrior was built without GnuTLS support. Sync is not available." -#define STRING_CMD_SYNC_INIT "Please confirm that you wish to upload all your pending tasks to the Taskserver" +#define STRING_CMD_SYNC_INIT "Please confirm that you wish to upload all your tasks to the Taskserver" #define STRING_CMD_SYNC_NO_INIT "Taskwarrior will not proceed with first-time sync initialization." #define STRING_CMD_SYNC_RELOCATE0 "The server account has been relocated. Please update your configuration using:" #define STRING_CMD_SYNC_RELOCATE1 "task config taskd.server {1}" diff --git a/src/l10n/fra-FRA.h b/src/l10n/fra-FRA.h index 46847ffa1..05d7e82e9 100644 --- a/src/l10n/fra-FRA.h +++ b/src/l10n/fra-FRA.h @@ -482,7 +482,7 @@ #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}'" #define STRING_CMD_SYNC_NO_TLS "Taskwarrior was built without GnuTLS support. Sync is not available." -#define STRING_CMD_SYNC_INIT "Please confirm that you wish to upload all your pending tasks to the Taskserver" +#define STRING_CMD_SYNC_INIT "Please confirm that you wish to upload all your tasks to the Taskserver" #define STRING_CMD_SYNC_NO_INIT "Taskwarrior will not proceed with first-time sync initialization." #define STRING_CMD_SYNC_RELOCATE0 "The server account has been relocated. Please update your configuration using:" #define STRING_CMD_SYNC_RELOCATE1 "task config taskd.server {1}" diff --git a/src/l10n/ita-ITA.h b/src/l10n/ita-ITA.h index 858b257da..d54af0588 100644 --- a/src/l10n/ita-ITA.h +++ b/src/l10n/ita-ITA.h @@ -481,7 +481,7 @@ #define STRING_CMD_SYNC_FAIL_CONNECT "Sincronizzazione fallita. Impossibile connettersi al Taskserver." #define STRING_CMD_SYNC_BAD_SERVER "Sincronizzazione fallita. Impostazione di configurazione '{1}' malformata" #define STRING_CMD_SYNC_NO_TLS "Taskwarrior was built without GnuTLS support. Sync is not available." -#define STRING_CMD_SYNC_INIT "Please confirm that you wish to upload all your pending tasks to the Taskserver" +#define STRING_CMD_SYNC_INIT "Please confirm that you wish to upload all your tasks to the Taskserver" #define STRING_CMD_SYNC_NO_INIT "Taskwarrior will not proceed with first-time sync initialization." #define STRING_CMD_SYNC_RELOCATE0 "The server account has been relocated. Please update your configuration using:" #define STRING_CMD_SYNC_RELOCATE1 "task config taskd.server {1}" diff --git a/src/l10n/jpn-JPN.h b/src/l10n/jpn-JPN.h index 4f53cba27..ff27b30f3 100644 --- a/src/l10n/jpn-JPN.h +++ b/src/l10n/jpn-JPN.h @@ -482,7 +482,7 @@ #define STRING_CMD_SYNC_FAIL_CONNECT "同期失敗。 Taskserverに接続できない。" #define STRING_CMD_SYNC_BAD_SERVER "同期失敗。 不正な形式の設定 '{1}'" #define STRING_CMD_SYNC_NO_TLS "Taskwarrior はGnuTLSサポートなしで構成されています。同期は無効です。" -#define STRING_CMD_SYNC_INIT "Please confirm that you wish to upload all your pending tasks to the Taskserver" +#define STRING_CMD_SYNC_INIT "Please confirm that you wish to upload all your tasks to the Taskserver" #define STRING_CMD_SYNC_NO_INIT "Taskwarrior will not proceed with first-time sync initialization." #define STRING_CMD_SYNC_RELOCATE0 "The server account has been relocated. Please update your configuration using:" #define STRING_CMD_SYNC_RELOCATE1 "task config taskd.server {1}" From d025f3deb6349f56a7fc49551e819cfe13f97917 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 31 Aug 2016 17:48:45 -0400 Subject: [PATCH 0086/1455] TW-1778: Unicode strings are truncated in task description - Thanks to Andrew, bjonnh, OKOMPer, Vladimir. --- AUTHORS | 4 ++++ ChangeLog | 2 ++ src/text.cpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 8681889f3..52d43edde 100644 --- a/AUTHORS +++ b/AUTHORS @@ -131,6 +131,7 @@ The following submitted code, packages or analysis, and deserve special thanks: Lynoure Braakman Sebastien Badia Ran Benita + Vladimir Thanks to the following, who submitted detailed bug reports and excellent suggestions: @@ -296,3 +297,6 @@ suggestions: Ellington Santos george js E. Manuel Cerr'on Angeles + Andrew + bjonnh + OKOMper diff --git a/ChangeLog b/ChangeLog index ca06056bd..323e99b65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,8 @@ (thanks to Paul Beckingham) - TW-1772 Implementation of circular dependency detection is inefficient (thanks to Michael Meier). +- TW-1778 Unicode strings are truncated in task description + (thanks to Andrew, bjonnh, OKOMPer, Vladimir). - TW-1788 Closing a reopened task does not update the end time (thanks to Ralph Bean). - TW-1791 taskrc(5) manpage: spurious "pri." in rule.precedence.color diff --git a/src/text.cpp b/src/text.cpp index f5e3496be..bc8353f73 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -248,7 +248,7 @@ bool extractLine ( // Premature EOL. if (character == '\n') { - line = text.substr (offset, line_length); + line = text.substr (offset, prior_cursor - offset); offset = cursor; return true; } From 4a48b8112b08172f83efbf3b36776b93ec235440 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 2 Sep 2016 08:08:12 -0400 Subject: [PATCH 0087/1455] Docs: Updated dev build instructions --- DEVELOPER | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/DEVELOPER b/DEVELOPER index 10c24f159..545557b14 100644 --- a/DEVELOPER +++ b/DEVELOPER @@ -8,12 +8,13 @@ How to Build Taskwarrior - 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 + $ git clone --recursive https://git.tasktools.org/scm/tm/task.git task.git $ cd task.git $ git checkout 2.6.0 # Latest dev branch - $ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither. + $ git submodule update # Update the libhsared.git submodule + $ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither $ make VERBOSE=1 -j8 # Shows details, builds using 8 jobs - # Alternately 'export MAKEFLAGS=-j 8'. + # Alternately 'export MAKEFLAGS=-j 8' Running Test Suite: $ cd tests From 0b729b5d97d1d8649d6ce8c16ddcaab2701b4467 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 4 Sep 2016 16:11:04 -0400 Subject: [PATCH 0088/1455] Config: Changed to 0/1 boolean values for the defaults. - Deprecated use of alternate Boolean configuration settings. Use values "0" for off, and "1" for on. Avoid used of "on", "off", "true", "t", "false", "f", "yes", "y", "no", "n". --- ChangeLog | 3 + NEWS | 3 + doc/man/taskrc.5.in | 171 ++++++++++++++++++++++---------------------- src/Config.cpp | 88 +++++++++++------------ 4 files changed, 136 insertions(+), 129 deletions(-) diff --git a/ChangeLog b/ChangeLog index 323e99b65..686d33275 100644 --- a/ChangeLog +++ b/ChangeLog @@ -40,6 +40,9 @@ - Added 'QUARTER' virtual tag. - Fixed unquoted glob in bash completion script (thanks to Ran Benita). +- Deprecated use of alternate Boolean configuration settings. Use values "0" for + off, and "1" for on. Avoid used of "on", "off", "true", "t", "false", "f", + "yes", "y", "no", "n". ------ current release --------------------------- diff --git a/NEWS b/NEWS index b54713bc4..1ecb47ad9 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,9 @@ Newly Deprecated Features in Taskwarrior 2.6.0 not needed. - The 'new-uuid' verbosity option is to be removed due to being redundant, its functionality will be merged with 'new-id' option. + - The use of alternate Boolean configuration settings is deprecated. Use values + "0" for off, and "1" for on. Avoid used of "on", "off", "true", "t", + "false", "f", "yes", "y", "no", "n". Removed Features in 2.6.0 diff --git a/doc/man/taskrc.5.in b/doc/man/taskrc.5.in index 837e94858..28c149701 100644 --- a/doc/man/taskrc.5.in +++ b/doc/man/taskrc.5.in @@ -68,8 +68,8 @@ The entry must be on a single line, no continuations. Values support UTF8 as well as JSON encoding, such as \\uNNNN. Note that Taskwarrior is flexible about the values used to represent Boolean -items. You can use "on", "yes", "y", "1" and "true". -Anything else means "off". +items. You can use "1" to enable, anything else is interpreted as disabled. +The values "on", "yes", "y" and "true" are currently supported by deprecated. .RS include @@ -181,33 +181,33 @@ shell meta character, which will be properly expanded. Note that the TASKDATA environment variable overrides this setting. .TP -.B locking=on +.B locking=1 Determines whether to use file locking when accessing the pending.data and -completed.data files. Defaults to "on". Solaris users who store the data -files on an NFS mount may need to set locking to "off". Note that there is -danger in setting this value to "off" - another program (or another instance of +completed.data files. Defaults to "1". Solaris users who store the data +files on an NFS mount may need to set locking to "0". Note that there is +danger in setting this value to "0" - another program (or another instance of task) may write to the task.pending file at the same time. .TP -.B gc=on +.B gc=1 Can be used to temporarily suspend garbage collection (gc), so that task IDs don't change. Note that this should be used in the form of a command line -override (task rc.gc=off ...), and not permanently used in the .taskrc file, +override (task rc.gc=0 ...), and not permanently used in the .taskrc file, as this significantly affects performance in the long term. .TP -.B hooks=on +.B hooks=1 This master control switch enables hook script processing. The default value -is 'on', but certain extensions and environments may need to disable hooks. +is '1', but certain extensions and environments may need to disable hooks. .TP -.B exit.on.missing.db=no -When set to 'yes' causes the program to exit if the database (~/.task or -rc.data.location or TASKDATA override) is missing. Default value is 'no'. +.B exit.on.missing.db=0 +When set to '1' causes the program to exit if the database (~/.task or +rc.data.location or TASKDATA override) is missing. Default value is '0'. .SS TERMINAL .TP -.B detection=on +.B detection=1 Determines whether to use ioctl to establish the size of the window you are using, for text wrapping. @@ -225,14 +225,14 @@ to 24. If set to 0, it is interpreted as infinite height. This is useful when re charts to a file for subsequent handling. .TP -.B avoidlastcolumn=no +.B avoidlastcolumn=0 Causes the width of the terminal minus one to be used as the full width. This avoids placing color codes in the last column which can cause problems for -Cygwin users. Default value is 'no'. +Cygwin users. Default value is '0'. .TP -.B hyphenate=on -Hyphenates lines when wrapping breaks occur mid-word. Default value is 'on'. +.B hyphenate=1 +Hyphenates lines when wrapping breaks occur mid-word. Default value is '1'. .TP .B editor=vi @@ -250,9 +250,9 @@ prompt. This is only referenced when 'limit:page' is used. .SS MISCELLANEOUS .TP -.B verbose=on|off|nothing|list... -When set to "on" (the default), helpful explanatory comments are added to all -output from Taskwarrior. Setting this to "off" means that you would see regular +.B verbose=1|0|nothing|list... +When set to "1" (the default), helpful explanatory comments are added to all +output from Taskwarrior. Setting this to "0" means that you would see regular output. The special value "nothing" can be used to eliminate all optional output, which @@ -280,15 +280,15 @@ control specific occasions when output is generated. This list may contain: "affected", "new-id", "new-uuid" "project" and "unwait" imply "footnote". -Note that the "on" setting is equivalent to all the tokens being specified, +Note that the "1" setting is equivalent to all the tokens being specified, and the "nothing" setting is equivalent to none of the tokens being specified. Here are the shortcut equivalents: - verbose=on + verbose=1 verbose=blank,header,footnote,label,new-id,affected,edit,special,project,sync,filter,unwait - verbose=off + verbose=0 verbose=blank,label,new-id,edit verbose=nothing @@ -298,16 +298,16 @@ Those additional comments are sent to the standard error for header, footnote and project. The others are sent to standard output. .TP -.B confirmation=yes -May be "yes" or "no", and determines whether Taskwarrior will ask for +.B confirmation=1 +May be "1" or "0", and determines whether Taskwarrior will ask for confirmation before deleting a task or performing the undo command. The default -value is "yes". Consider leaving this setting as "yes", for safety. +value is "1". Consider leaving this enabled, for safety. .TP -.B allow.empty.filter=yes +.B allow.empty.filter=1 An empty filter combined with a write command is potentially a way to modify all tasks by mistake, and when this is detected, confirmation is required. -Setting this to 'no' means that it is an error to use a write command with no +Setting this to '0' means that it is an error to use a write command with no filter. .TP @@ -344,47 +344,47 @@ Default value is: 'You have more urgent tasks'. It is a gentle reminder that you are contradicting your own urgency settings. .TP -.B list.all.projects=no -May be yes or no, and determines whether the 'projects' command lists all the project +.B list.all.projects=0 +May be "1" or "0", and determines whether the 'projects' command lists all the project names you have used, or just the ones used in active tasks. The default value is -"no". +"0". .TP -.B summary.all.projects=no -If set to yes, shows all projects in the summary report, even if there are no -pending tasks. The default value is "no". +.B summary.all.projects=0 +If set to "1", shows all projects in the summary report, even if there are no +pending tasks. The default value is "0". .TP -.B complete.all.tags=yes -May be yes or no, and determines whether the tab completion scripts consider all +.B complete.all.tags=1 +May be "1" or "0", and determines whether the tab completion scripts consider all the tag names you have used, or just the ones used in active tasks. The default -value is "no". +value is "0". .TP -.B list.all.tags=yes -May be yes or no, and determines whether the 'tags' command lists all the tag +.B list.all.tags=1 +May be "1" or "0", and determines whether the 'tags' command lists all the tag names you have used, or just the ones used in active tasks. The default value is -"no". +"0". .TP -.B print.empty.columns=no -May be yes or no, and determines whether columns with no data for any task are -printed. Defaults to no. +.B print.empty.columns=1 +May be "1" or "0", and determines whether columns with no data for any task are +printed. Defaults to "0". .TP -.B search.case.sensitive=yes -May be yes or no, and determines whether keyword lookup and substitutions on the -description and annotations are done in a case sensitive way. Defaults to yes on -most platforms. Defaults to no on Cygwin due to older regex library problems with +.B search.case.sensitive=1 +May be "1" or "0", and determines whether keyword lookup and substitutions on the +description and annotations are done in a case sensitive way. Defaults to "1" on +most platforms. Defaults to "0" on Cygwin due to older regex library problems with case-insensitivity. .TP -.B regex=on -Controls whether regular expression support is enabled. The default value is on. +.B regex=1 +Controls whether regular expression support is enabled. The default value is "1". .TP -.B xterm.title=no -Sets the xterm window title when reports are run. Defaults to off. +.B xterm.title=1 +Sets the xterm window title when reports are run. Defaults to "0". .TP .B expressions=infix|postfix @@ -392,21 +392,21 @@ Sets a preference for infix expressions (1 + 2) or postfix expressions (1 2 +). Defaults to infix. .TP -.B json.array=on +.B json.array=1 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. +With json.array=0, export writes raw JSON objects to STDOUT, one per line. +Defaults to "1". .TP -.B json.depends.array=on +.B json.depends.array=1 Determines whether the export command encodes dependencies as an array of string UUIDs, or one comma-separated string. -Defaults to on. +Defaults to "1". .TP -.B _forcecolor=no +.B _forcecolor=1 Taskwarrior shuts off color automatically when the output is not sent directly to a TTY. For example, this command: @@ -422,6 +422,8 @@ $ task rc._forcecolor=yes list > file .RE .RE +Defaults to "0". + .TP .B active.indicator=* The character or string to show in the start.active column. Defaults to *. @@ -439,9 +441,9 @@ The character or string to show in the depends.indicator column. Defaults to +. The character or string to show in the .indicator column. Defaults to U. .TP -.B recurrence=yes +.B recurrence=1 Controls whether recurrence is enabled, and whether recurring tasks continue to -generate new task instances. Defaults to 'yes'. +generate new task instances. Defaults to "1". .TP .B recurrence.confirmation=prompt @@ -475,7 +477,7 @@ Minimum length of any abbreviated command/value. This means that "ve", "ver", Default is 2. .TP -.B debug=off +.B debug=0 Taskwarrior has a debug mode that causes diagnostic output to be displayed. Typically this is not something anyone would want, but when reporting a bug, debug output can be useful. It can also help explain how the command line is @@ -483,7 +485,7 @@ being parsed, but the information is displayed in a developer-friendly, not a user-friendly way. Turning debug on automatically sets debug.hooks=1, debug.parser=1 and debug.tls=2 -if they do not already have assigned values. +if they do not already have assigned values. Defaults to "0". .TP .B debug.hooks=0 @@ -647,8 +649,8 @@ field that is set. Otherwise, they are set to the corresponding values of .RE .TP -.B date.iso=yes -Enables ISO-8601 date support. The default value is "yes". +.B date.iso=1 +Enables ISO-8601 date support. The default value is "1". .TP .B weekstart=Sunday @@ -656,10 +658,10 @@ Determines the day a week starts. Valid values are Sunday or Monday only. The default value is "Sunday". .TP -.B displayweeknumber=yes +.B displayweeknumber=1 Determines if week numbers are displayed when using the "task calendar" command. The week number is dependent on the day a week starts. The default value is -"yes". +"1". .TP .B due=7 @@ -681,9 +683,9 @@ The report to run when displaying the details of tasks with due dates when running the "task calendar" command. The default value is "list". .TP -.B calendar.offset=off -If "on" the first month in the calendar report is effectively changed by the -offset value specified in calendar.offset.value. It defaults to "off". +.B calendar.offset=0 +If "1" the first month in the calendar report is effectively changed by the +offset value specified in calendar.offset.value. It defaults to "0". .TP .B calendar.offset.value=-1 @@ -699,15 +701,15 @@ and no details on the holidays will be displayed. The displaying of holidays is turned off by setting the variable to none. The default value is "none". .TP -.B calendar.legend=yes -Determines whether the calendar legend is displayed. The default value is "yes". +.B calendar.legend=1 +Determines whether the calendar legend is displayed. The default value is "1". .SS JOURNAL ENTRIES .TP -.B journal.time=no -May be yes or no, and determines whether the 'start' and 'stop' commands should -record an annotation when being executed. The default value is "no". The text of +.B journal.time=0 +May be "1" or "0", and determines whether the 'start' and 'stop' commands should +record an annotation when being executed. The default value is "0". The text of the corresponding annotations is controlled by: .TP @@ -721,9 +723,9 @@ The text of the annotation that is recorded when executing the stop command and having set journal.time. .TP -.B journal.info=on +.B journal.info=1 When enabled, this setting causes a change log of each task to be displayed by -the 'info' command. Default value is "on". +the 'info' command. Default value is "1". .SS HOLIDAYS Holidays are entered either directly in the .taskrc file or via an include file @@ -782,22 +784,22 @@ specified, Taskwarrior will only show as many that will fit. .SS DEPENDENCIES .TP -.B dependency.reminder=on +.B dependency.reminder=1 Determines whether dependency chain violations generate reminders. .TP -.B dependency.confirmation=yes +.B dependency.confirmation=1 Determines whether dependency chain repair requires confirmation. .SS COLOR CONTROLS .TP -.B color=on -May be "on" or "off". Determines whether Taskwarrior uses color. When "off", +.B color=1 +May be "1" or "0". Determines whether Taskwarrior uses color. When "0", will use dashes (-----) to underline column headings. .TP -.B fontunderline=on +.B fontunderline=1 Determines if font underlines or ASCII dashes should be used to underline headers, even when color is enabled. .RE @@ -880,12 +882,11 @@ 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 +.B rule.color.merge=1 +Can be "1" or "0". When "0", 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 @@ -1151,7 +1152,7 @@ The coefficients reflect the relative importance of the various terms in the 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 +.B urgency.inherit=0 .RS Not actually a coefficient. When enabled, blocking tasks inherit the highest urgency value found in the tasks they block. This is diff --git a/src/Config.cpp b/src/Config.cpp index 92e9ff146..c82e1b813 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -61,45 +61,45 @@ std::string Config::_defaults = "\n" "# Files\n" "data.location=~/.task\n" - "locking=on # Use file-level locking\n" - "gc=on # Garbage-collect data files - DO NOT CHANGE unless you are sure\n" - "exit.on.missing.db=no # Whether to exit if ~/.task is not found\n" - "hooks=on # Master control switch for hooks\n" + "locking=1 # Use file-level locking\n" + "gc=1 # Garbage-collect data files - DO NOT CHANGE unless you are sure\n" + "exit.on.missing.db=0 # Whether to exit if ~/.task is not found\n" + "hooks=1 # Master control switch for hooks\n" "\n" "# Terminal\n" - "detection=on # Detects terminal width\n" + "detection=1 # Detects terminal width\n" "defaultwidth=80 # Without detection, assumed width\n" "defaultheight=24 # Without detection, assumed height\n" - "avoidlastcolumn=no # Fixes Cygwin width problem\n" - "hyphenate=on # Hyphenates lines wrapped on non-word-breaks\n" + "avoidlastcolumn=0 # Fixes Cygwin width problem\n" + "hyphenate=1 # Hyphenates lines wrapped on non-word-breaks\n" "#editor=vi # Preferred text editor\n" "reserved.lines=1 # Assume a 1-line prompt\n" "\n" "# Miscellaneous\n" "# # Comma-separated list. May contain any subset of:\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" + "confirmation=1 # Confirmation on delete, big changes\n" + "recurrence=1 # Enable recurrence\n" "recurrence.confirmation=prompt # Confirmation for propagating changes among recurring tasks (yes/no/prompt)\n" - "allow.empty.filter=yes # An empty filter gets a warning and requires confirmation\n" + "allow.empty.filter=1 # An empty filter gets a warning and requires confirmation\n" "indent.annotation=2 # Indent spaces for annotations\n" "indent.report=0 # Indent spaces for whole report\n" "row.padding=0 # Left and right padding for each row of report\n" "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 - "search.case.sensitive=yes # Setting to no allows case insensitive searches\n" + "search.case.sensitive=1 # Setting to no allows case insensitive searches\n" "active.indicator=* # What to show as an active task indicator\n" "tag.indicator=+ # What to show as a tag indicator\n" "dependency.indicator=D # What to show as a dependency indicator\n" "recurrence.indicator=R # What to show as a task recurrence indicator\n" "recurrence.limit=1 # Number of future recurring pending tasks\n" "undo.style=side # Undo style - can be 'side', or 'diff'\n" - "regex=yes # Assume all search/filter strings are regexes\n" - "xterm.title=no # Sets xterm title for some commands\n" + "regex=1 # Assume all search/filter strings are regexes\n" + "xterm.title=0 # Sets xterm title for some commands\n" "expressions=infix # Prefer infix over postfix expressions\n" - "json.array=on # Enclose JSON output in [ ]\n" - "json.depends.array=off # Encode dependencies as a JSON array\n" + "json.array=1 # Enclose JSON output in [ ]\n" + "json.depends.array=0 # Encode dependencies as a JSON array\n" "abbreviation.minimum=2 # Shortest allowed abbreviation\n" "\n" "# Dates\n" @@ -109,31 +109,31 @@ std::string Config::_defaults = "dateformat.info=Y-M-D H:N:S # Preferred display date format for information\n" "dateformat.report= # Preferred display date format for reports\n" "dateformat.annotation= # Preferred display date format for annotations\n" - "date.iso=yes # Enable ISO date support\n" + "date.iso=1 # Enable ISO date support\n" "weekstart=" STRING_DATE_SUNDAY " # Sunday or Monday only\n" - "displayweeknumber=yes # Show week numbers on calendar\n" + "displayweeknumber=1 # Show week numbers on calendar\n" "due=7 # Task is considered due in 7 days\n" "\n" "# Calendar controls\n" - "calendar.legend=yes # Display the legend on calendar\n" + "calendar.legend=1 # Display the legend on calendar\n" "calendar.details=sparse # Calendar shows information for tasks w/due dates: full, sparse or none\n" "calendar.details.report=list # Report to use when showing task information in cal\n" - "calendar.offset=no # Apply an offset value to control the first month of the calendar\n" + "calendar.offset=0 # Apply an offset value to control the first month of the calendar\n" "calendar.offset.value=-1 # The number of months the first month of the calendar is moved\n" "calendar.holidays=none # Show public holidays on calendar:full, sparse or none\n" "#monthsperline=3 # Number of calendar months on a line\n" "\n" "# Journal controls\n" - "journal.time=no # Record start/stop commands as annotation\n" + "journal.time=0 # Record start/stop commands as annotation\n" "journal.time.start.annotation=Started task # Annotation description for the start journal entry\n" "journal.time.stop.annotation=Stopped task # Annotation description for the stop journal entry\n" - "journal.info=on # Display task journal with info command\n" + "journal.info=1 # Display task journal with info command\n" "\n" "# Dependency controls\n" - "dependency.reminder=on # Nags on dependency chain violations\n" - "dependency.confirmation=on # Should dependency chain repair be confirmed?\n" + "dependency.reminder=1 # Nags on dependency chain violations\n" + "dependency.confirmation=1 # Should dependency chain repair be confirmed?\n" "\n" "# Urgency Coefficients\n" "urgency.user.tag.next.coefficient=15.0 # Urgency coefficient for 'next' special tag\n" @@ -147,7 +147,7 @@ std::string Config::_defaults = "urgency.project.coefficient=1.0 # Urgency coefficient for projects\n" "urgency.blocked.coefficient=-5.0 # Urgency coefficient for blocked 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.inherit=0 # 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" @@ -155,12 +155,12 @@ std::string Config::_defaults = "#urgency.uda.foo.coefficient=5.0 # Urgency coefficients for UDA 'foo'\n" "\n" "# Color controls.\n" - "color=on # Enable color\n" + "color=1 # Enable color\n" "\n" "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" + "rule.color.merge=1\n" "color.label=\n" "color.label.sort=\n" "color.alternate=on gray2\n" @@ -249,23 +249,23 @@ std::string Config::_defaults = "#default.due=eom # Default due date for 'add' command\n" "default.command=next # When no arguments are specified\n" "\n" - "_forcecolor=no # Forces color to be on, even for non TTY output\n" - "complete.all.tags=no # Include old tag names in '_ags' command\n" - "list.all.projects=no # Include old project names in 'projects' command\n" - "summary.all.projects=no # Include old project names in 'summary' command\n" - "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" + "_forcecolor=0 # Forces color to be on, even for non TTY output\n" + "complete.all.tags=0 # Include old tag names in '_ags' command\n" + "list.all.projects=0 # Include old project names in 'projects' command\n" + "summary.all.projects=0 # Include old project names in 'summary' command\n" + "list.all.tags=0 # Include old tag names in 'tags' command\n" + "print.empty.columns=0 # Print columns which have no data for any task\n" + "debug=0 # Display diagnostics\n" + "sugar=1 # Syntactic sugar\n" + "obfuscate=0 # Obfuscate data for error reporting\n" + "fontunderline=1 # Uses underlines rather than -------\n" "\n" "# WARNING: Please read the documentation (man task-sync) before setting up\n" "# Taskwarrior for Taskserver synchronization.\n" - "#taskd.ca \n" - "#taskd.certificate \n" - "#taskd.credentials //\n" - "#taskd.server :\n" + "#taskd.ca=\n" + "#taskd.certificate=\n" + "#taskd.credentials=//\n" + "#taskd.server=:\n" "taskd.trust=strict\n" "#taskd.trust=ignore hostname\n" "#taskd.trust=allow all\n" @@ -594,12 +594,12 @@ bool Config::getBoolean (const std::string& key) { std::string value = Lexer::lowerCase ((*this)[key]); if (value == "t" || // TODO Deprecate - value == "true" || + value == "true" || // TODO Deprecate value == "1" || value == "+" || // TODO Deprecate - value == "y" || - value == "yes" || - value == "on" || + value == "y" || // TODO Deprecate + value == "yes" || // TODO Deprecate + value == "on" || // TODO Deprecate value == "enable" || // TODO Deprecate value == "enabled") // TODO Deprecate return true; From d8bf209f290f319b59f2fd0eaeecd220ffd3ad9f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 4 Sep 2016 16:13:23 -0400 Subject: [PATCH 0089/1455] Tests: Updated to non-deprecated Boolean values --- test/annotate.t | 4 ++-- test/basetest/task.py | 2 +- test/bulk.t | 34 +++++++++++++++++----------------- test/encoding.t | 2 +- test/enpassant.t | 4 ++-- test/exec.t | 2 +- test/feature.559.t | 2 +- test/feature.default.project.t | 2 +- test/gc.t | 6 +++--- test/hyphenate.t | 4 ++-- test/import.t | 6 +++--- test/project.t | 2 +- test/rc.override.t | 8 ++++---- test/recurrence.t | 6 +++--- test/show.t | 2 +- test/special.t | 2 +- test/start.t | 4 ++-- test/substitute.t | 4 ++-- test/sugar.t | 4 ++-- test/tdb2.t.cpp | 4 ++-- test/urgency.t | 2 +- test/urgency_inherit.t | 6 +++--- test/verbose.t | 2 +- 23 files changed, 57 insertions(+), 57 deletions(-) diff --git a/test/annotate.t b/test/annotate.t index 630397667..1424b8260 100755 --- a/test/annotate.t +++ b/test/annotate.t @@ -81,7 +81,7 @@ class TestAnnotate(TestCase): self.t.config("report.rrr.columns", "id,description") self.t.config("report.rrr.sort", "id+") self.t.config("dateformat", "m/d/Y") - self.t.config("color", "off") + self.t.config("color", "0") code, out, err = self.t("rrr") @@ -154,7 +154,7 @@ class TestAnnotation(TestCase): def setUp(self): """Executed before each test in the class""" self.t = Task() - self.t.config("confirmation", "yes") + self.t.config("confirmation", "1") def test_blank_annotation(self): """Verify blank annotations are prevented""" diff --git a/test/basetest/task.py b/test/basetest/task.py index 35d0af84f..f83bb0358 100644 --- a/test/basetest/task.py +++ b/test/basetest/task.py @@ -72,7 +72,7 @@ class Task(object): def activate_hooks(self): """Enable self.hooks functionality and activate hooks on config """ - self.config("hooks", "on") + self.config("hooks", "1") self.hooks = Hooks(self.datadir) def reset_env(self): diff --git a/test/bulk.t b/test/bulk.t index a6b88d707..38f276e96 100755 --- a/test/bulk.t +++ b/test/bulk.t @@ -47,50 +47,50 @@ class TestBulk(TestCase): self.t("add three") def test_bulk_confirmations_single_confirmation_off(self): - """not bulk delete 1 tasks with confirmation:off deletes it""" + """not bulk delete 1 tasks with confirmation:0 deletes it""" # Test with 1 task. 1 is a special case. - code, out, err = self.t("1 delete rc.confirmation:off") + code, out, err = self.t("1 delete rc.confirmation:0") self.assertNotIn("(yes/no)", out) self.assertNotIn("(yes/no/all/quit)", out) self.assertIn("Deleting task 1", out) def test_bulk_confirmations_single_confirmation_on(self): - """not bulk delete 1 task with confirmation:on and input >y deletes it""" + """not bulk delete 1 task with confirmation:1 and input >y deletes it""" # Test with 1 task. 1 is a special case. - code, out, err = self.t("2 delete rc.confirmation:on", input="y\n") + code, out, err = self.t("2 delete rc.confirmation:1", input="y\n") self.assertIn("(yes/no)", out) self.assertNotIn("(yes/no/all/quit)", out) self.assertIn("Deleting task 2", out) def test_bulk_confirmations_double_confirmation_off(self): - """not bulk delete 2 tasks with confirmation:off deletes them""" + """not bulk delete 2 tasks with confirmation:0 deletes them""" # Test with 2 tasks. 2 is greater than 1 and less than bulk. - code, out, err = self.t("1-2 delete rc.confirmation:off") + code, out, err = self.t("1-2 delete rc.confirmation:0") self.assertNotIn("(yes/no)", out) self.assertNotIn("(yes/no/all/quit)", out) self.assertIn("Deleting task 1", out) self.assertIn("Deleting task 2", out) def test_bulk_confirmations_double_confirmation_on(self): - """not bulk delete 2 tasks with confirmation:on and input >y >y deletes them""" + """not bulk delete 2 tasks with confirmation:1 and input >y >y deletes them""" # Test with 2 tasks. 2 is greater than 1 and less than bulk. - code, out, err = self.t("1-2 delete rc.confirmation:on", input="y\ny\n") + code, out, err = self.t("1-2 delete rc.confirmation:1", input="y\ny\n") self.assertNotIn("(yes/no)", out) self.assertIn("(yes/no/all/quit)", out) self.assertIn("Deleting task 1", out) self.assertIn("Deleting task 2", out) def test_bulk_confirmations_bulk_confirmation_off(self): - """bulk delete 3 tasks with confirmation:off always prompts""" + """bulk delete 3 tasks with confirmation:0 always prompts""" # Test with 3 tasks. 3 is considered bulk. rc.confirmation has no effect on bulk # Delete task 1 'one'? (yes/no/all/quit) --> timeout - code, out, err = self.t.runError("1-3 delete rc.confirmation:off") + code, out, err = self.t.runError("1-3 delete rc.confirmation:0") self.assertNotIn("(yes/no)", out) self.assertIn("(yes/no/all/quit)", out) self.assertNotIn("Deleting task", out) @@ -102,7 +102,7 @@ class TestBulk(TestCase): # Delete task 2 'two'? (yes/no/all/quit) Deleting task 2 'two'. # Delete task 3 'three'? (yes/no/all/quit) Deleting task 3 'three'. # Deleted 3 tasks. - code, out, err = self.t("1-3 delete rc.confirmation:off", input="y\ny\ny\n") + code, out, err = self.t("1-3 delete rc.confirmation:0", input="y\ny\ny\n") self.assertNotIn("(yes/no)", out) self.assertIn("(yes/no/all/quit)", out) self.assertIn("Deleting task 1", out) @@ -113,7 +113,7 @@ class TestBulk(TestCase): """bulk delete 3 tasks with confirmation:on and input >y >y >y deletes them""" # Test with 3 tasks. 3 is considered bulk. rc.confirmation has no effect on bulk - code, out, err = self.t("1-3 delete rc.confirmation:on", input="y\ny\ny\n") + code, out, err = self.t("1-3 delete rc.confirmation:1", input="y\ny\ny\n") self.assertNotIn("(yes/no)", out) self.assertIn("(yes/no/all/quit)", out) self.assertIn("Deleting task 1", out) @@ -124,14 +124,14 @@ class TestBulk(TestCase): """bulk delete >no deletes nothing""" # Test with 1 task, denying delete. - code, out, err = self.t.runError("1 delete rc.confirmation:on", input="n\n") + code, out, err = self.t.runError("1 delete rc.confirmation:1", input="n\n") self.assertIn("(yes/no)", out) self.assertNotIn("(yes/no/all/quit)", out) self.assertNotIn("Deleted task 1", out) self.assertNotIn("Deleting task", out) # Test with 2 tasks, denying delete. - code, out, err = self.t.runError("1-2 delete rc.confirmation:on", input="n\nn\n") + code, out, err = self.t.runError("1-2 delete rc.confirmation:1", input="n\nn\n") self.assertNotIn("(yes/no)", out) self.assertIn("(yes/no/all/quit)", out) self.assertNotIn("Deleted task 1", out) @@ -139,7 +139,7 @@ class TestBulk(TestCase): self.assertNotIn("Deleting task", out) # Test with 3 tasks, denying delete. - code, out, err = self.t.runError("1-3 delete rc.confirmation:on", input="n\nn\nn\n") + code, out, err = self.t.runError("1-3 delete rc.confirmation:1", input="n\nn\nn\n") self.assertNotIn("(yes/no)", out) self.assertIn("(yes/no/all/quit)", out) self.assertNotIn("Deleted task 1", out) @@ -150,7 +150,7 @@ class TestBulk(TestCase): def test_bulk_delete_all_tests(self): """bulk delete >all deletes everything""" - code, out, err = self.t("1-3 delete rc.confirmation:on", input="all\n") + code, out, err = self.t("1-3 delete rc.confirmation:1", input="all\n") self.assertNotIn("(yes/no)", out) self.assertIn("(yes/no/all/quit)", out) self.assertIn("Deleting task 1", out) @@ -161,7 +161,7 @@ class TestBulk(TestCase): def test_bulk_delete_quit_tests(self): """bulk delete >quit deletes nothing""" - code, out, err = self.t.runError("1-3 delete rc.confirmation:on", input="quit\n") + code, out, err = self.t.runError("1-3 delete rc.confirmation:1", input="quit\n") self.assertNotIn("(yes/no)", out) self.assertIn("(yes/no/all/quit)", out) self.assertIn("Deleted 0 tasks", out) diff --git a/test/encoding.t b/test/encoding.t index 94921dcfd..6fa8e84b1 100755 --- a/test/encoding.t +++ b/test/encoding.t @@ -63,7 +63,7 @@ class TestUtf8(TestCase): """Text alignment in reports with wide utf8 characters""" # Originally Bug #455 - Text alignment in reports is broken when text # contains wide utf8 characters - self.t.config("print.empty.columns", "no") + self.t.config("print.empty.columns", "0") self.t(("add", "abc", "pro:Bar\u263a")) self.t("add def pro:Foo") diff --git a/test/enpassant.t b/test/enpassant.t index 9b9923a93..493ef07df 100755 --- a/test/enpassant.t +++ b/test/enpassant.t @@ -40,7 +40,7 @@ class BaseTestEnpassant(TestCase): """Executed before each test in the class""" self.t = Task() # No journal log which may contain the words we are looking for - self.t.config("journal.info", "off") + self.t.config("journal.info", "0") class TestEnpassantMultiple(BaseTestEnpassant): @@ -84,7 +84,7 @@ class TestEnpassant(BaseTestEnpassant): def setUp(self): super(TestEnpassant, self).setUp() - self.t.config("confirmation", "off") + self.t.config("confirmation", "0") self.t("add one") self.t("add two") diff --git a/test/exec.t b/test/exec.t index 1a2772449..9eac88756 100755 --- a/test/exec.t +++ b/test/exec.t @@ -40,7 +40,7 @@ class TestBug1414(TestCase): def setUp(self): self.t = Task() self.t.config("default.command", "exec echo hello") - self.t.config("verbose", "no") + self.t.config("verbose", "0") def test_execute(self): """use execute""" diff --git a/test/feature.559.t b/test/feature.559.t index b248916d0..3b342a013 100755 --- a/test/feature.559.t +++ b/test/feature.559.t @@ -40,7 +40,7 @@ class TestFeature559(TestCase): def setUp(self): self.t = Task() - self.t.config("exit.on.missing.db", "yes") + self.t.config("exit.on.missing.db", "1") # NOTE the framework uses TASKDATA and TASKRC to tell taskwarrior where # data is stored. Since these env variables take precedence over diff --git a/test/feature.default.project.t b/test/feature.default.project.t index f997d1747..b0aca793b 100755 --- a/test/feature.default.project.t +++ b/test/feature.default.project.t @@ -131,7 +131,7 @@ class TestDefaultProject(TestCase): def test_time_default_project(self): """default.project is not applied when start/stop'ing a task""" # Allow keeping track of time spent on task - self.t.config("journal.time", "yes") + self.t.config("journal.time", "1") self.t("add foobar") code, out, err = self.t("1 info") diff --git a/test/gc.t b/test/gc.t index 49d7c2e84..436e174d1 100755 --- a/test/gc.t +++ b/test/gc.t @@ -47,14 +47,14 @@ class TestGC(TestCase): def test_gc_off_id(self): """ID retained when GC off""" - self.t.config("gc", "off") + self.t.config("gc", "0") self.t("1 done") code, out, err = self.t("gctest") self.assertRegexpMatches(out, "1\s+one", "should still have ID") def test_gc_off_mod(self): """mod by ID after done with gc off""" - self.t.config("gc", "off") + self.t.config("gc", "0") self.t("1 done") self.t("gctest") self.t("2 mod +TWO") @@ -63,7 +63,7 @@ class TestGC(TestCase): def test_gc_on_id(self): """IDs reshuffle after report when GC on""" - self.t.config("gc", "on") + self.t.config("gc", "1") self.t("1 done") self.t("2 mod +TWO") code, out, err = self.t("gctest") diff --git a/test/hyphenate.t b/test/hyphenate.t index a62482c98..15dfb4fae 100755 --- a/test/hyphenate.t +++ b/test/hyphenate.t @@ -40,7 +40,7 @@ class TestHyphenation(TestCase): """Executed before each test in the class""" self.t = Task() self.t.config("defaultwidth", "20") - self.t.config("detection", "off") + self.t.config("detection", "0") self.t.config("verbose", "nothing") def test_hyphenation_on_space(self): @@ -63,7 +63,7 @@ class TestBug804(TestCase): def test_hyphenation(self): """Verify hyphenation is controllable""" - self.t.config("print.empty.columns", "yes") + self.t.config("print.empty.columns", "1") self.t.config("report.unittest.labels", "ID,Project,Pri,Description") self.t.config("report.unittest.columns", "id,project,priority,description") self.t.config("report.unittest.filter", "status:pending") diff --git a/test/import.t b/test/import.t index 1318f72a2..311a126ff 100755 --- a/test/import.t +++ b/test/import.t @@ -192,7 +192,7 @@ class TestImport(TestCase): _data = """{"uuid":"a0000000-a000-a000-a000-a00000000000","depends":"a1111111-a111-a111-a111-a11111111111","description":"zero","project":"A","status":"pending","entry":"1234567889"}""" self.t("import", input=self.data1) self.t("import", input=_data) - self.t.config("json.depends.array", "off") + self.t.config("json.depends.array", "0") _t = self.t.export("a0000000-a000-a000-a000-a00000000000")[0] self.assertEqual(_t["depends"], "a1111111-a111-a111-a111-a11111111111") @@ -242,8 +242,8 @@ class TestImportExportRoundtrip(TestCase): self.t2 = Task() for client in (self.t1, self.t2): - client.config("dateformat", "m/d/Y") - client.config("verbose", "off") + client.config("dateformat", "m/d/Y") + client.config("verbose", "0") client.config("defaultwidth", "100") def _validate_data(self, client): diff --git a/test/project.t b/test/project.t index 6bdfcb7ad..12d6aca03 100755 --- a/test/project.t +++ b/test/project.t @@ -397,7 +397,7 @@ class TestBug899(TestCase): def setUp(self): """Executed before each test in the class""" self.t = Task() - self.t.config("verbose", "on") + self.t.config("verbose", "1") def test_log_project(self): """899: Verify task log behaves correctly when logging into a project""" diff --git a/test/rc.override.t b/test/rc.override.t index 38a208590..89d457451 100755 --- a/test/rc.override.t +++ b/test/rc.override.t @@ -40,16 +40,16 @@ class TestOverride(TestCase): def setUp(self): """Executed before each test in the class""" self.t = Task() - self.t.config("regex", "off") + self.t.config("regex", "0") self.t.config("verbose", "nothing") def test_override(self): """Verify override is displayed in 'show' command""" code, out, err = self.t("show regex") - self.assertRegexpMatches(out, r"regex +off") + self.assertRegexpMatches(out, r"regex +0") - code, out, err = self.t("rc.regex:on show regex") - self.assertRegexpMatches(out, r"regex +on") + code, out, err = self.t("rc.regex:1 show regex") + self.assertRegexpMatches(out, r"regex +1") class TestRCSegfault(TestCase): diff --git a/test/recurrence.t b/test/recurrence.t index 7e8fbfc5b..1895df312 100755 --- a/test/recurrence.t +++ b/test/recurrence.t @@ -77,7 +77,7 @@ class TestRecurrenceDisabled(TestCase): disabled. """ - self.t.config("recurrence", "no") + self.t.config("recurrence", "0") self.t("add due:today recur:daily Recurrent task.") # Trigger GC, expect no match and therefore non-zero code @@ -325,7 +325,7 @@ class TestBug955(TestCase): """ # With confirmation:off the first "n\n" has no effect. - self.t.config("confirmation", "off") + self.t.config("confirmation", "0") code, out, err = self.t("2 delete", input="n\ny\n") self.assertIn("Deleting task 2", out) self.assertIn("Deleted 1 task", out) @@ -351,7 +351,7 @@ class TestBug955(TestCase): """ # With confirmation:on the first "n\n" is obeyed. - self.t.config("confirmation", "on") + self.t.config("confirmation", "1") code, out, err = self.t.runError("2 delete", input="n\ny\n") self.assertIn("Deleted 0 tasks.", out) diff --git a/test/show.t b/test/show.t index 1631d3b55..75d831df4 100755 --- a/test/show.t +++ b/test/show.t @@ -80,7 +80,7 @@ class TestShowHelperCommand(TestCase): def test_show_helper_no_arg(self): """Verify _show command lists all with no arg provided""" code, out, err = self.t("_show") - self.assertIn("debug=no\n", out) + self.assertIn("debug=0\n", out) self.assertIn("verbose=", out) diff --git a/test/special.t b/test/special.t index bc5cd5f65..496bd4ce4 100755 --- a/test/special.t +++ b/test/special.t @@ -47,7 +47,7 @@ class TestSpecialTags(TestCase): cls.t.config("color.pri.H", "") cls.t.config("color.completed", "") cls.t.config("nag", "NAG") - cls.t.config("color", "on") + cls.t.config("color", "1") cls.t.config("_forcecolor", "1") def test_nocolor(self): diff --git a/test/start.t b/test/start.t index 63befe283..cb439d0aa 100755 --- a/test/start.t +++ b/test/start.t @@ -69,7 +69,7 @@ class TestStart(TestCase): def test_journal_time(self): """Verify journal.time tracks state""" - self.t.config("journal.time", "on") + self.t.config("journal.time", "1") self.t("add one") self.t("1 start") @@ -82,7 +82,7 @@ class TestStart(TestCase): def test_journal_annotations(self): """Verify journal start/stop annotations are used""" - self.t.config("journal.time", "on") + self.t.config("journal.time", "1") self.t.config("journal.time.start.annotation", "Nu kör vi") self.t.config("journal.time.stop.annotation", "Nu stannar vi") diff --git a/test/substitute.t b/test/substitute.t index 0836ac182..bc527508c 100755 --- a/test/substitute.t +++ b/test/substitute.t @@ -43,7 +43,7 @@ class TestSubstitutions(TestCase): def test_substitution(self): """Verify substitution for task description""" - self.t.config("regex", "off") + self.t.config("regex", "0") self.t("add foo foo foo") self.t("1 modify /foo/FOO/") @@ -78,7 +78,7 @@ class TestSubstitutions(TestCase): def test_substitution_regex(self): """Verify regex substitution for task description""" - self.t.config("regex", "on") + self.t.config("regex", "1") self.t("add aaa bbb") self.t("1 modify /b{3}/BbB/") code, out, err = self.t("_get 1.description") diff --git a/test/sugar.t b/test/sugar.t index 9154baf36..bb7b950ad 100755 --- a/test/sugar.t +++ b/test/sugar.t @@ -50,7 +50,7 @@ class TestSugar(TestCase): self.assertIn("two", out) self.assertNotIn("three", out) - self.t.config("sugar", "off") + self.t.config("sugar", "0") code, out, err = self.t("1 2 count") self.assertEqual(0, int(out)) @@ -64,7 +64,7 @@ class TestSugar(TestCase): self.assertIn("three", out) # sugar off: WYSIWYG parsing. - self.t.config("sugar", "off") + self.t.config("sugar", "0") code, out, err = self.t("3 and '( 2 three )' count") self.assertEqual(0, int(out)) diff --git a/test/tdb2.t.cpp b/test/tdb2.t.cpp index 933a6fe84..afcb6d2af 100644 --- a/test/tdb2.t.cpp +++ b/test/tdb2.t.cpp @@ -52,8 +52,8 @@ int main (int, char**) unlink ("./backlog.data"); // Set the context to allow GC. - context.config.set ("gc", "on"); - context.config.set ("debug", "on"); + context.config.set ("gc", 1); + context.config.set ("debug", 1); context.tdb2.set_location ("."); diff --git a/test/urgency.t b/test/urgency.t index e7e6f7b8d..ae7ab5cf3 100755 --- a/test/urgency.t +++ b/test/urgency.t @@ -54,7 +54,7 @@ class TestUrgency(TestCase): cls.t.config("urgency.user.tag.next.coefficient", "10") cls.t.config("urgency.user.project.PROJECT.coefficient", "10") cls.t.config("urgency.user.tag.TAG.coefficient", "10") - cls.t.config("confirmation", "off") + cls.t.config("confirmation", "0") cls.t("add control") # 1 diff --git a/test/urgency_inherit.t b/test/urgency_inherit.t index 66e3eee77..fe8058d4d 100755 --- a/test/urgency_inherit.t +++ b/test/urgency_inherit.t @@ -62,16 +62,16 @@ class TestUrgencyInherit(TestCase): def test_urgency_inherit_off(self): """No urgency inheritance when switched off""" - self.t.config("urgency.inherit", "off") + self.t.config("urgency.inherit", "0") tl = self.get_tasks() self.assertTrue(tl[1]["urgency"] <= tl[2]["urgency"] < tl[3]["urgency"]) def test_gc_off_mod(self): """Biggest urgency is inherited recursively""" - self.t.config("urgency.inherit", "off") + self.t.config("urgency.inherit", "0") tl = self.get_tasks() oldmax = max(tl[1]["urgency"], tl[2]["urgency"], tl[3]["urgency"]) - self.t.config("urgency.inherit", "on") + self.t.config("urgency.inherit", "1") tl = self.get_tasks() self.assertTrue(oldmax <= tl[3]["urgency"]) self.assertTrue(tl[1]["urgency"] >= tl[2]["urgency"] >= tl[3]["urgency"]) diff --git a/test/verbose.t b/test/verbose.t index eb3607500..27378528d 100755 --- a/test/verbose.t +++ b/test/verbose.t @@ -41,7 +41,7 @@ from basetest import Task, TestCase class TestVerbosity(TestCase): def setUp(self): self.t = Task() - self.t.config("print.empty.columns", "yes") + self.t.config("print.empty.columns", "1") self.t("add Sample") From 9fc71ff3ecf201efd806a5dd8fe4cce649784284 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 5 Sep 2016 08:52:17 -0400 Subject: [PATCH 0090/1455] Docs: Removed old reference to support forums --- INSTALL | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/INSTALL b/INSTALL index 1c6a5e862..0c4ec138c 100644 --- a/INSTALL +++ b/INSTALL @@ -192,8 +192,7 @@ CMake with no reported problems, and the build will fail later. This is almost always because CMake is mistaken about some assumption. If a build does not succeed, please send the contents of the 'CMakeCache.txt' -and 'CMakeFiles/CMakeOutput.log' files to support@taskwarrior.org, or post a -message in the support forums at taskwarrior.org along with the information. +and 'CMakeFiles/CMakeOutput.log' files to support@taskwarrior.org. If CMake runs but Taskwarrior does not build, please send the contents of the above files as well as a transcript from the build, which is not written to a From 66915635c8622ec840616207d4165324c1a4d57f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 9 Sep 2016 21:37:37 -0400 Subject: [PATCH 0091/1455] Build: Eliminated compiler warning --- src/ISO8601.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ISO8601.cpp b/src/ISO8601.cpp index 8a94621b5..0830c21fd 100644 --- a/src/ISO8601.cpp +++ b/src/ISO8601.cpp @@ -707,9 +707,12 @@ bool ISO8601d::parse_date_time_ext (Nibbler& n) parse_time_ext (n)) { if (n.skip ('Z')) + { _utc = true; + } else if (parse_off_ext (n)) - ; + { + } if (! Lexer::isDigit (n.next ())) return true; From 0df3e3b0d966fe249623a190f1402c3d3464736e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 18:58:31 -0400 Subject: [PATCH 0092/1455] ColDescription: Don't use string literals when character literals are needed --- src/columns/ColDescription.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/columns/ColDescription.cpp b/src/columns/ColDescription.cpp index fdd1eba2e..82e6721fa 100644 --- a/src/columns/ColDescription.cpp +++ b/src/columns/ColDescription.cpp @@ -61,15 +61,15 @@ ColumnDescription::ColumnDescription () std::string a3 = STRING_COLUMN_EXAMPLES_ANNO3; std::string a4 = STRING_COLUMN_EXAMPLES_ANNO4; - _examples = {d + "\n " + t + " " + a1 - + "\n " + t + " " + a2 - + "\n " + t + " " + a3 - + "\n " + t + " " + a4, + _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 + ' ' + t + ' ' + a1 + + ' ' + t + ' ' + a2 + + ' ' + t + ' ' + a3 + + ' ' + t + ' ' + a4, d.substr (0, 20) + "...", d + " [4]", d.substr (0, 20) + "... [4]"}; From df1cf61421c7843416c5bbedfdb49030d5a206c5 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 19:01:46 -0400 Subject: [PATCH 0093/1455] ColDue: Removed unused includes --- src/columns/ColDue.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/columns/ColDue.cpp b/src/columns/ColDue.cpp index 1b9b04901..2cf64a79e 100644 --- a/src/columns/ColDue.cpp +++ b/src/columns/ColDue.cpp @@ -26,15 +26,13 @@ #include #include -#include -#include #include //////////////////////////////////////////////////////////////////////////////// ColumnDue::ColumnDue () { - _name = "due"; - _label = STRING_COLUMN_LABEL_DUE; + _name = "due"; + _label = STRING_COLUMN_LABEL_DUE; } //////////////////////////////////////////////////////////////////////////////// From 03c404bc8fc61cedfe8934becd89bf4908932113 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 19:02:06 -0400 Subject: [PATCH 0094/1455] ColIMask: Removed unused includes --- src/columns/ColIMask.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/columns/ColIMask.cpp b/src/columns/ColIMask.cpp index eaf3871af..97ef05143 100644 --- a/src/columns/ColIMask.cpp +++ b/src/columns/ColIMask.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include From ba0674b53f0c3e4b77891b774cfa634da96aa5a8 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 19:02:17 -0400 Subject: [PATCH 0095/1455] ColMask: Removed unused includes --- src/columns/ColMask.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/columns/ColMask.cpp b/src/columns/ColMask.cpp index 3e8459ebe..a00d7b8a8 100644 --- a/src/columns/ColMask.cpp +++ b/src/columns/ColMask.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include From 184e89cddda5bb950d6d7f6e0a32d8de75d7cd8e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 19:02:28 -0400 Subject: [PATCH 0096/1455] ColParent: Removed unused includes --- src/columns/ColParent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/columns/ColParent.cpp b/src/columns/ColParent.cpp index ac7c0300b..3d1622c0b 100644 --- a/src/columns/ColParent.cpp +++ b/src/columns/ColParent.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include From 4d83ed8588f119886f521ca440f8d9526adaf746 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 19:02:46 -0400 Subject: [PATCH 0097/1455] ColScheduled: Removed unused includes --- src/columns/ColScheduled.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/columns/ColScheduled.cpp b/src/columns/ColScheduled.cpp index 87cd7f223..bd3beeb13 100644 --- a/src/columns/ColScheduled.cpp +++ b/src/columns/ColScheduled.cpp @@ -26,8 +26,6 @@ #include #include -#include -#include #include //////////////////////////////////////////////////////////////////////////////// From 5403675100a7c1e7e7c2f676379f010264f6ba3a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 20:51:19 -0400 Subject: [PATCH 0098/1455] libshared: Updated to d84d1bc70b14c85af771bb5cc7299c290d5372b5 --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index 144d37263..d84d1bc70 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit 144d37263c52aef3e0959e1b891785da3911ece5 +Subproject commit d84d1bc70b14c85af771bb5cc7299c290d5372b5 From 95f4989f7706b382e1702fd6fd213d603328afbf Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 22:27:34 -0400 Subject: [PATCH 0099/1455] Cleanup: Don't use string literals when character literals are needed --- src/CLI2.cpp | 22 +++--- src/Color.cpp | 2 +- src/Config.cpp | 4 +- src/Context.cpp | 42 ++++++------ src/DOM.cpp | 2 +- src/TLSClient.cpp | 2 +- src/Task.cpp | 4 +- src/Timer.cpp | 2 +- src/calc.cpp | 28 ++++---- src/columns/ColDescription.cpp | 4 +- src/commands/CmdAdd.cpp | 8 +-- src/commands/CmdAliases.cpp | 2 +- src/commands/CmdAnnotate.cpp | 2 +- src/commands/CmdAppend.cpp | 2 +- src/commands/CmdAttributes.cpp | 2 +- src/commands/CmdBurndown.cpp | 10 +-- src/commands/CmdCalc.cpp | 4 +- src/commands/CmdCalendar.cpp | 12 ++-- src/commands/CmdColor.cpp | 100 +++++++++++++-------------- src/commands/CmdColumns.cpp | 6 +- src/commands/CmdCommands.cpp | 6 +- src/commands/CmdConfig.cpp | 10 +-- src/commands/CmdContext.cpp | 16 ++--- src/commands/CmdCount.cpp | 2 +- src/commands/CmdCustom.cpp | 2 +- src/commands/CmdDelete.cpp | 4 +- src/commands/CmdDenotate.cpp | 4 +- src/commands/CmdDiagnostics.cpp | 90 ++++++++++++------------- src/commands/CmdDone.cpp | 4 +- src/commands/CmdDuplicate.cpp | 10 +-- src/commands/CmdEdit.cpp | 116 ++++++++++++++++---------------- src/commands/CmdExport.cpp | 4 +- src/commands/CmdGet.cpp | 2 +- src/commands/CmdHelp.cpp | 9 ++- src/commands/CmdHistory.cpp | 30 ++++----- src/commands/CmdIDs.cpp | 18 ++--- src/commands/CmdImport.cpp | 10 +-- src/commands/CmdInfo.cpp | 14 ++-- src/commands/CmdLog.cpp | 2 +- src/commands/CmdLogo.cpp | 2 +- src/commands/CmdModify.cpp | 2 +- src/commands/CmdPrepend.cpp | 2 +- src/commands/CmdProjects.cpp | 8 +-- src/commands/CmdReports.cpp | 2 +- src/commands/CmdShow.cpp | 24 +++---- src/commands/CmdStart.cpp | 4 +- src/commands/CmdStop.cpp | 4 +- src/commands/CmdSummary.cpp | 4 +- src/commands/CmdSync.cpp | 16 ++--- src/commands/CmdTags.cpp | 4 +- src/commands/CmdTimesheet.cpp | 18 ++--- src/commands/CmdUDAs.cpp | 8 +-- src/commands/CmdUnique.cpp | 2 +- src/commands/CmdUrgency.cpp | 2 +- src/commands/CmdVersion.cpp | 20 +++--- src/commands/Command.cpp | 2 +- src/dependency.cpp | 7 +- src/feedback.cpp | 2 +- 58 files changed, 372 insertions(+), 374 deletions(-) diff --git a/src/CLI2.cpp b/src/CLI2.cpp index a6c1305b7..c8a2d06db 100644 --- a/src/CLI2.cpp +++ b/src/CLI2.cpp @@ -213,7 +213,7 @@ const std::string A2::dump () const else tags += "\033[32m" + tag + "\033[0m "; } - return output + " " + atts + tags; + return output + ' ' + atts + tags; } //////////////////////////////////////////////////////////////////////////////// @@ -632,7 +632,7 @@ void CLI2::prepareFilter () if (a.hasTag ("FILTER")) { if (combined != "") - combined += " "; + combined += ' '; combined += a.attribute ("raw"); } @@ -657,7 +657,7 @@ const std::vector CLI2::getWords () Color colorOrigArgs ("gray10 on gray4"); std::string message = " "; for (const auto& word : words) - message += colorOrigArgs.colorize (word) + " "; + message += colorOrigArgs.colorize (word) + ' '; context.debug ("CLI2::getWords" + message); } @@ -737,13 +737,13 @@ const std::string CLI2::dump (const std::string& title) const out << colorFilter.colorize (i->attribute ("raw")); } - out << "\n"; + out << '\n'; if (_args.size ()) { out << " _args\n"; for (const auto& a : _args) - out << " " << a.dump () << "\n"; + out << " " << a.dump () << '\n'; } if (_id_ranges.size ()) @@ -752,21 +752,21 @@ const std::string CLI2::dump (const std::string& title) const for (const auto& range : _id_ranges) { if (range.first != range.second) - out << colorArgs.colorize (range.first + "-" + range.second) << " "; + out << colorArgs.colorize (range.first + "-" + range.second) << ' '; else - out << colorArgs.colorize (range.first) << " "; + out << colorArgs.colorize (range.first) << ' '; } - out << "\n"; + out << '\n'; } if (_uuid_list.size ()) { out << " _uuid_list\n "; for (const auto& uuid : _uuid_list) - out << colorArgs.colorize (uuid) << " "; + out << colorArgs.colorize (uuid) << ' '; - out << "\n"; + out << '\n'; } return out.str (); @@ -1242,7 +1242,7 @@ void CLI2::desugarFilterAttributes () std::vector values = lexExpression (value); if (context.config.getInteger ("debug.parser") >= 2) { - context.debug ("CLI2::lexExpression " + name + ":" + value); + context.debug ("CLI2::lexExpression " + name + ':' + value); for (auto& v : values) context.debug (" " + v.dump ()); context.debug (" "); diff --git a/src/Color.cpp b/src/Color.cpp index 05be8acd0..557fdfea6 100644 --- a/src/Color.cpp +++ b/src/Color.cpp @@ -308,7 +308,7 @@ Color::operator std::string () const if (_value & _COLOR_BRIGHT) description += std::string (description.length () ? " " : "") + "bright"; - description += " " + bg (); + description += ' ' + bg (); } return description; diff --git a/src/Config.cpp b/src/Config.cpp index c82e1b813..3cbe612af 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -489,7 +489,7 @@ void Config::createDefaultRC (const std::string& rc, const std::string& data) std::stringstream contents; contents << "# [Created by " << PACKAGE_STRING - << " " + << ' ' << now.toString ("m/d/Y H:N:S") << "]\n" << _defaults.substr (0, loc + 14) @@ -509,7 +509,7 @@ void Config::createDefaultRC (const std::string& rc, const std::string& data) << "#include " << TASK_RCDIR << "/solarized-dark-256.theme\n" << "#include " << TASK_RCDIR << "/solarized-light-256.theme\n" << "#include " << TASK_RCDIR << "/no-color.theme\n" - << "\n"; + << '\n'; // Write out the new file. if (! File::write (rc, contents.str ())) diff --git a/src/Context.cpp b/src/Context.cpp index 98edcd635..3d8c3e34e 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -273,9 +273,9 @@ int Context::initialize (int argc, const char** argv) { 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. @@ -283,9 +283,9 @@ int Context::initialize (int argc, const char** argv) { 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. @@ -293,18 +293,18 @@ int Context::initialize (int argc, const char** argv) { 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. 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 (); @@ -329,13 +329,13 @@ int Context::run () std::stringstream s; s << "Perf " << PACKAGE_STRING - << " " + << ' ' #ifdef HAVE_COMMIT << COMMIT #else - << "-" + << '-' #endif - << " " + << ' ' << ISO8601d ().toISO () << " init:" << timer_init.total () @@ -356,7 +356,7 @@ int Context::run () timer_render.total () - timer_hooks.total () << " total:" << timer_total.total () - << "\n"; + << '\n'; debug (s.str ()); } @@ -383,9 +383,9 @@ int Context::run () { 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. @@ -393,9 +393,9 @@ int Context::run () { 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. @@ -406,18 +406,18 @@ int Context::run () { 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. 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; } @@ -819,7 +819,7 @@ void Context::updateXtermTitle () title += a->attribute ("raw"); } - std::cout << "]0;task " << command << " " << title << ""; + std::cout << "]0;task " << command << ' ' << title << ""; } } diff --git a/src/DOM.cpp b/src/DOM.cpp index 43fd96233..f1b06bbd9 100644 --- a/src/DOM.cpp +++ b/src/DOM.cpp @@ -90,7 +90,7 @@ bool getDOM (const std::string& name, Variant& value) for (auto& arg : context.cli2._original_args) { if (commandLine != "") - commandLine += " "; + commandLine += ' '; commandLine += arg.attribute("raw"); } diff --git a/src/TLSClient.cpp b/src/TLSClient.cpp index cb87d1d46..512de5bf1 100644 --- a/src/TLSClient.cpp +++ b/src/TLSClient.cpp @@ -56,7 +56,7 @@ static int verify_certificate_callback (gnutls_session_t); //////////////////////////////////////////////////////////////////////////////// static void gnutls_log_function (int level, const char* message) { - std::cout << "c: " << level << " " << message; + std::cout << "c: " << level << ' ' << message; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Task.cpp b/src/Task.cpp index 6a9e10f13..f8a0165b7 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -2144,12 +2144,12 @@ void Task::modify (modType type, bool text_required /* = false */) case modPrepend: context.debug (label + "description <-- '" + text + "' + description"); - set ("description", text + " " + get ("description")); + set ("description", text + ' ' + get ("description")); break; case modAppend: context.debug (label + "description <-- description + '" + text + "'"); - set ("description", get ("description") + " " + text); + set ("description", get ("description") + ' ' + text); break; case modAnnotate: diff --git a/src/Timer.cpp b/src/Timer.cpp index 0455903a5..ed41c55c9 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -55,7 +55,7 @@ Timer::~Timer () std::stringstream s; s << "Timer " << _description - << " " + << ' ' << std::setprecision (6) << std::fixed << _total / 1000000.0 diff --git a/src/calc.cpp b/src/calc.cpp index 681f6af00..cf50b8695 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -57,7 +57,7 @@ int main (int argc, char** argv) try { - bool infix = true; + bool infix {true}; // Add a source for constants. Eval e; @@ -69,29 +69,29 @@ int main (int argc, char** argv) for (int i = 1; i < argc; i++) if (!strcmp (argv[i], "-h") || ! strcmp (argv[i], "--help")) { - std::cout << "\n" + std::cout << '\n' << "Usage: " << argv[0] << " [options] ''\n" - << "\n" + << '\n' << "Options:\n" << " -h|--help Display this usage\n" << " -d|--debug Debug mode\n" << " -i|--infix Infix expression (default)\n" << " -p|--postfix Postfix expression\n" - << "\n"; + << '\n'; exit (1); } else if (!strcmp (argv[i], "-v") || !strcmp (argv[i], "--version")) { - std::cout << "\n" + std::cout << '\n' << format (STRING_CMD_VERSION_BUILT, "calc", VERSION) << osName () - << "\n" + << '\n' << STRING_CMD_VERSION_COPY - << "\n" - << "\n" + << '\n' + << '\n' << STRING_CMD_VERSION_MIT - << "\n" - << "\n"; + << '\n' + << '\n'; exit (1); } @@ -102,7 +102,7 @@ int main (int argc, char** argv) else if (!strcmp (argv[i], "-p") || !strcmp (argv[i], "--postfix")) infix = false; else - expression += std::string (argv[i]) + " "; + expression += std::string (argv[i]) + ' '; Variant result; if (infix) @@ -112,16 +112,16 @@ int main (int argc, char** argv) // Show any debug output. for (auto& i : context.debugMessages) - std::cout << i << "\n"; + std::cout << i << '\n'; // Show the result in string form. std::cout << (std::string) result - << "\n"; + << '\n'; } catch (const std::string& error) { - std::cerr << error << "\n"; + std::cerr << error << '\n'; status = -1; } diff --git a/src/columns/ColDescription.cpp b/src/columns/ColDescription.cpp index 82e6721fa..700d71cf3 100644 --- a/src/columns/ColDescription.cpp +++ b/src/columns/ColDescription.cpp @@ -182,7 +182,7 @@ void ColumnDescription::render ( for (const auto& i : annos) { ISO8601d dt (strtol (i.first.substr (11).c_str (), NULL, 10)); - description += "\n" + std::string (_indent, ' ') + dt.toString (_dateformat) + " " + i.second; + description += '\n' + std::string (_indent, ' ') + dt.toString (_dateformat) + ' ' + i.second; } } @@ -213,7 +213,7 @@ void ColumnDescription::render ( for (const auto& i : annos) { ISO8601d dt (strtol (i.first.substr (11).c_str (), NULL, 10)); - description += " " + dt.toString (_dateformat) + " " + i.second; + description += ' ' + dt.toString (_dateformat) + ' ' + i.second; } } diff --git a/src/commands/CmdAdd.cpp b/src/commands/CmdAdd.cpp index bc85dbe03..efca8d798 100644 --- a/src/commands/CmdAdd.cpp +++ b/src/commands/CmdAdd.cpp @@ -63,19 +63,19 @@ int CmdAdd::execute (std::string& output) if (context.verbose ("new-id") && (status == Task::pending || status == Task::waiting)) - output += format (STRING_CMD_ADD_FEEDBACK, task.id) + "\n"; + output += format (STRING_CMD_ADD_FEEDBACK, task.id) + '\n'; else if (context.verbose ("new-id") && status == Task::recurring) - output += format (STRING_CMD_ADD_RECUR, task.id) + "\n"; + output += format (STRING_CMD_ADD_RECUR, task.id) + '\n'; else if (context.verbose ("new-uuid") && status != Task::recurring) - output += format (STRING_CMD_ADD_FEEDBACK, task.get ("uuid")) + "\n"; + output += format (STRING_CMD_ADD_FEEDBACK, task.get ("uuid")) + '\n'; else if (context.verbose ("new-uuid") && status == Task::recurring) - output += format (STRING_CMD_ADD_RECUR, task.get ("uuid")) + "\n"; + output += format (STRING_CMD_ADD_RECUR, task.get ("uuid")) + '\n'; if (context.verbose ("project")) context.footnote (onProjectChange (task)); diff --git a/src/commands/CmdAliases.cpp b/src/commands/CmdAliases.cpp index 75963044b..a46b01bde 100644 --- a/src/commands/CmdAliases.cpp +++ b/src/commands/CmdAliases.cpp @@ -53,7 +53,7 @@ int CmdCompletionAliases::execute (std::string& output) { for (auto& alias : context.config) if (alias.first.substr (0, 6) == "alias.") - output += alias.first.substr (6) + "\n"; + output += alias.first.substr (6) + '\n'; return 0; } diff --git a/src/commands/CmdAnnotate.cpp b/src/commands/CmdAnnotate.cpp index b7e632209..932ee027b 100644 --- a/src/commands/CmdAnnotate.cpp +++ b/src/commands/CmdAnnotate.cpp @@ -118,7 +118,7 @@ int CmdAnnotate::execute (std::string&) } else { - std::cout << STRING_CMD_ANNO_NO << "\n"; + std::cout << STRING_CMD_ANNO_NO << '\n'; rc = 1; if (_permission_quit) break; diff --git a/src/commands/CmdAppend.cpp b/src/commands/CmdAppend.cpp index dbc811e9d..5be95aee9 100644 --- a/src/commands/CmdAppend.cpp +++ b/src/commands/CmdAppend.cpp @@ -118,7 +118,7 @@ int CmdAppend::execute (std::string&) } else { - std::cout << STRING_CMD_APPEND_NO << "\n"; + std::cout << STRING_CMD_APPEND_NO << '\n'; rc = 1; if (_permission_quit) break; diff --git a/src/commands/CmdAttributes.cpp b/src/commands/CmdAttributes.cpp index dfd621090..f83743d31 100644 --- a/src/commands/CmdAttributes.cpp +++ b/src/commands/CmdAttributes.cpp @@ -60,7 +60,7 @@ int CmdZshAttributes::execute (std::string& output) std::stringstream out; for (auto& col : columns) - out << col << ":" << col << "\n"; + out << col << ":" << col << '\n'; output = out.str (); return 0; diff --git a/src/commands/CmdBurndown.cpp b/src/commands/CmdBurndown.cpp index 5151b3712..7fca5be75 100644 --- a/src/commands/CmdBurndown.cpp +++ b/src/commands/CmdBurndown.cpp @@ -405,13 +405,13 @@ std::string Chart::render () if (_graph_height < 5 || // a 4-line graph is essentially unreadable. _graph_width < 2) // A single-bar graph is useless. { - return std::string (STRING_CMD_BURN_TOO_SMALL) + "\n"; + 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"; + return std::string (STRING_CMD_BURN_TOO_LARGE) + '\n'; } if (_max_value == 0) @@ -420,7 +420,7 @@ std::string Chart::render () // Create a grid, folded into a string. _grid = ""; for (int i = 0; i < _height; ++i) - _grid += std::string (_width, ' ') + "\n"; + _grid += std::string (_width, ' ') + '\n'; // Title. std::string full_title; @@ -437,7 +437,7 @@ std::string Chart::render () { if (full_title.length () + 1 + _title.length () < (unsigned) _width) { - full_title += " " + _title; + full_title += ' ' + _title; _grid.replace (LOC (0, (_width - full_title.length ()) / 2), full_title.length (), full_title); } else @@ -494,7 +494,7 @@ std::string Chart::render () _grid.replace (LOC (_height - 5, _max_label + 3 + ((_actual_bars - bar._offset - 1) * 3)), bar._minor_label.length (), bar._minor_label); if (_major_label != bar._major_label) - _grid.replace (LOC (_height - 4, _max_label + 2 + ((_actual_bars - bar._offset - 1) * 3)), bar._major_label.length (), " " + bar._major_label); + _grid.replace (LOC (_height - 4, _max_label + 2 + ((_actual_bars - bar._offset - 1) * 3)), bar._major_label.length (), ' ' + bar._major_label); _major_label = bar._major_label; } diff --git a/src/commands/CmdCalc.cpp b/src/commands/CmdCalc.cpp index 20c50f79c..bd16c6daf 100644 --- a/src/commands/CmdCalc.cpp +++ b/src/commands/CmdCalc.cpp @@ -69,7 +69,7 @@ int CmdCalc::execute (std::string& output) // Compile all the args into one expression. std::string expression; for (auto& word : context.cli2.getWords ()) - expression += word + " "; + expression += word + ' '; // Evaluate according to preference. Variant result; @@ -78,7 +78,7 @@ int CmdCalc::execute (std::string& output) else e.evaluatePostfixExpression (expression, result); - output = (std::string) result + "\n"; + output = (std::string) result + '\n'; return 0; } diff --git a/src/commands/CmdCalendar.cpp b/src/commands/CmdCalendar.cpp index 36a9823ad..f71e6e8c2 100644 --- a/src/commands/CmdCalendar.cpp +++ b/src/commands/CmdCalendar.cpp @@ -225,7 +225,7 @@ int CmdCalendar::execute (std::string& output) int details_mFrom = mFrom; std::stringstream out; - out << "\n"; + out << '\n'; while (yFrom < yTo || (yFrom == yTo && mFrom <= mTo)) { @@ -269,10 +269,10 @@ int CmdCalendar::execute (std::string& output) } } - out << "\n" + out << '\n' << optionalBlankLine () << renderMonths (mFrom, yFrom, today, tasks, monthsPerLine) - << "\n"; + << '\n'; mFrom += monthsPerLine; if (mFrom > 12) @@ -306,9 +306,9 @@ int CmdCalendar::execute (std::string& output) << color_holiday.colorize ("holiday") << ", " << color_weeknumber.colorize ("weeknumber") - << "." + << '.' << optionalBlankLine () - << "\n"; + << '\n'; if (context.config.get ("calendar.details") == "full" || context.config.get ("calendar.holidays") == "full") { @@ -409,7 +409,7 @@ int CmdCalendar::execute (std::string& output) out << optionalBlankLine () << holTable.render () - << "\n"; + << '\n'; } } diff --git a/src/commands/CmdColor.cpp b/src/commands/CmdColor.cpp index 6fe0e3b2e..7262c614c 100644 --- a/src/commands/CmdColor.cpp +++ b/src/commands/CmdColor.cpp @@ -71,7 +71,7 @@ int CmdColor::execute (std::string& output) // use. if (legend) { - out << "\n" << STRING_CMD_COLOR_HERE << "\n"; + out << '\n' << STRING_CMD_COLOR_HERE << '\n'; ViewText view; view.width (context.getWidth ()); @@ -94,7 +94,7 @@ int CmdColor::execute (std::string& output) } out << view.render () - << "\n"; + << '\n'; } // If there is something in the description, then assume that is a color, @@ -112,26 +112,26 @@ int CmdColor::execute (std::string& output) for (auto word = words.begin (); word != words.end (); ++word) { if (word != words.begin ()) - swatch += " "; + swatch += ' '; swatch += *word; } Color sample (swatch); - out << "\n" - << STRING_CMD_COLOR_EXPLANATION << "\n" + out << '\n' + << STRING_CMD_COLOR_EXPLANATION << '\n' << "\n\n" - << STRING_CMD_COLOR_16 << "\n" - << " " << one.colorize ("task color black on bright yellow") << "\n" - << " " << two.colorize ("task color underline cyan on bright blue") << "\n" - << "\n" - << STRING_CMD_COLOR_256 << "\n" - << " " << three.colorize ("task color color214 on color202") << "\n" - << " " << four.colorize ("task color rgb150 on rgb020") << "\n" - << " " << five.colorize ("task color underline grey10 on grey3") << "\n" - << " " << six.colorize ("task color red on color173") << "\n" - << "\n" + << STRING_CMD_COLOR_16 << '\n' + << " " << one.colorize ("task color black on bright yellow") << '\n' + << " " << two.colorize ("task color underline cyan on bright blue") << '\n' + << '\n' + << STRING_CMD_COLOR_256 << '\n' + << " " << three.colorize ("task color color214 on color202") << '\n' + << " " << four.colorize ("task color rgb150 on rgb020") << '\n' + << " " << five.colorize ("task color underline grey10 on grey3") << '\n' + << " " << six.colorize ("task color red on color173") << '\n' + << '\n' << STRING_CMD_COLOR_YOURS << "\n\n" << " " << sample.colorize ("task color " + swatch) << "\n\n"; } @@ -139,41 +139,41 @@ int CmdColor::execute (std::string& output) // Show all supported colors. Possibly show some unsupported ones too. else { - out << "\n" + out << '\n' << STRING_CMD_COLOR_BASIC - << "\n" - << " " << Color::colorize (" black ", "black") - << " " << Color::colorize (" red ", "red") - << " " << Color::colorize (" blue ", "blue") - << " " << Color::colorize (" green ", "green") - << " " << Color::colorize (" magenta ", "magenta") - << " " << Color::colorize (" cyan ", "cyan") - << " " << Color::colorize (" yellow ", "yellow") - << " " << Color::colorize (" white ", "white") - << "\n" - << " " << Color::colorize (" black ", "white on black") - << " " << Color::colorize (" red ", "white on red") - << " " << Color::colorize (" blue ", "white on blue") - << " " << Color::colorize (" green ", "black on green") - << " " << Color::colorize (" magenta ", "black on magenta") - << " " << Color::colorize (" cyan ", "black on cyan") - << " " << Color::colorize (" yellow ", "black on yellow") - << " " << Color::colorize (" white ", "black on white") + << '\n' + << ' ' << Color::colorize (" black ", "black") + << ' ' << Color::colorize (" red ", "red") + << ' ' << Color::colorize (" blue ", "blue") + << ' ' << Color::colorize (" green ", "green") + << ' ' << Color::colorize (" magenta ", "magenta") + << ' ' << Color::colorize (" cyan ", "cyan") + << ' ' << Color::colorize (" yellow ", "yellow") + << ' ' << Color::colorize (" white ", "white") + << '\n' + << ' ' << Color::colorize (" black ", "white on black") + << ' ' << Color::colorize (" red ", "white on red") + << ' ' << Color::colorize (" blue ", "white on blue") + << ' ' << Color::colorize (" green ", "black on green") + << ' ' << Color::colorize (" magenta ", "black on magenta") + << ' ' << Color::colorize (" cyan ", "black on cyan") + << ' ' << Color::colorize (" yellow ", "black on yellow") + << ' ' << Color::colorize (" white ", "black on white") << "\n\n"; out << STRING_CMD_COLOR_EFFECTS - << "\n" - << " " << Color::colorize (" red ", "red") - << " " << Color::colorize (" bold red ", "bold red") - << " " << Color::colorize (" underline on blue ", "underline on blue") - << " " << Color::colorize (" on green ", "black on green") - << " " << Color::colorize (" on bright green ", "black on bright green") - << " " << Color::colorize (" inverse ", "inverse") + << '\n' + << ' ' << Color::colorize (" red ", "red") + << ' ' << Color::colorize (" bold red ", "bold red") + << ' ' << Color::colorize (" underline on blue ", "underline on blue") + << ' ' << Color::colorize (" on green ", "black on green") + << ' ' << Color::colorize (" on bright green ", "black on bright green") + << ' ' << Color::colorize (" inverse ", "inverse") << "\n\n"; // 16 system colors. out << "color0 - color15" - << "\n" + << '\n' << " 0 1 2 . . .\n"; for (int r = 0; r < 2; ++r) { @@ -185,7 +185,7 @@ int CmdColor::execute (std::string& output) out << Color::colorize (" ", s.str ()); } - out << "\n"; + out << '\n'; } out << " . . . 15\n\n"; @@ -200,21 +200,21 @@ int CmdColor::execute (std::string& output) << Color::colorize ("5", "bold green") << Color::colorize ("5", "bold blue") << " (also color16 - color231)" - << "\n" + << '\n' << " " << Color::colorize ("0 " "1 " "2 " "3 " "4 " "5", "bold red") - << "\n" + << '\n' << " " << Color::colorize ("0 1 2 3 4 5 " "0 1 2 3 4 5 " "0 1 2 3 4 5 " "0 1 2 3 4 5 " "0 1 2 3 4 5 " "0 1 2 3 4 5", "bold blue") - << "\n"; + << '\n'; char label [12]; for (int g = 0; g < 6; ++g) @@ -230,13 +230,13 @@ int CmdColor::execute (std::string& output) out << Color::colorize (" ", s.str ()); } - out << " "; + out << ' '; } - out << "\n"; + out << '\n'; } - out << "\n"; + out << '\n'; // Grey ramp. out << STRING_CMD_COLOR_RAMP @@ -257,7 +257,7 @@ int CmdColor::execute (std::string& output) } else { - out << STRING_CMD_COLOR_OFF << "\n"; + out << STRING_CMD_COLOR_OFF << '\n'; rc = 1; } diff --git a/src/commands/CmdColumns.cpp b/src/commands/CmdColumns.cpp index 759c4ed17..3696bb802 100644 --- a/src/commands/CmdColumns.cpp +++ b/src/commands/CmdColumns.cpp @@ -119,9 +119,9 @@ int CmdColumns::execute (std::string& output) output = optionalBlankLine () + formats.render () - + "\n" + + '\n' + STRING_CMD_COLUMNS_NOTE - + "\n"; + + '\n'; return 0; } @@ -154,7 +154,7 @@ int CmdCompletionColumns::execute (std::string& output) // Render only the column names. for (auto& name : names) - output += name + "\n"; + output += name + '\n'; return 0; } diff --git a/src/commands/CmdCommands.cpp b/src/commands/CmdCommands.cpp index 9875481a8..cb6a51dc7 100644 --- a/src/commands/CmdCommands.cpp +++ b/src/commands/CmdCommands.cpp @@ -119,7 +119,7 @@ int CmdCommands::execute (std::string& output) output = optionalBlankLine () + view.render () + optionalBlankLine () - + "\n"; + + '\n'; return 0; } @@ -154,7 +154,7 @@ int CmdCompletionCommands::execute (std::string& output) std::stringstream out; for (auto& c : commands) - out << c << "\n"; + out << c << '\n'; output = out.str (); return 0; @@ -226,7 +226,7 @@ int CmdZshCommands::execute (std::string& output) for (auto& zc : commands) out << zc._command << ":" << Command::categoryNames.at (zc._category) << ":" - << zc._description << "\n"; + << zc._description << '\n'; output = out.str (); return 0; diff --git a/src/commands/CmdConfig.cpp b/src/commands/CmdConfig.cpp index 8f9a6f8f4..932cc7136 100644 --- a/src/commands/CmdConfig.cpp +++ b/src/commands/CmdConfig.cpp @@ -77,7 +77,7 @@ bool CmdConfig::setConfigVariable (std::string name, std::string value, bool con 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); @@ -178,7 +178,7 @@ int CmdConfig::execute (std::string& output) for (unsigned int i = 1; i < words.size (); ++i) { if (i > 1) - value += " "; + value += ' '; value += words[i]; } @@ -214,10 +214,10 @@ int CmdConfig::execute (std::string& output) { out << format (STRING_CMD_CONFIG_FILE_MOD, context.config._original_file._data) - << "\n"; + << '\n'; } else - out << STRING_CMD_CONFIG_NO_CHANGE << "\n"; + out << STRING_CMD_CONFIG_NO_CHANGE << '\n'; } else throw std::string (STRING_CMD_CONFIG_NO_NAME); @@ -254,7 +254,7 @@ int CmdCompletionConfig::execute (std::string& output) std::sort (configs.begin (), configs.end ()); for (auto& config : configs) - output += config + "\n"; + output += config + '\n'; return 0; } diff --git a/src/commands/CmdContext.cpp b/src/commands/CmdContext.cpp index e507f4036..eae0dbdd1 100644 --- a/src/commands/CmdContext.cpp +++ b/src/commands/CmdContext.cpp @@ -94,7 +94,7 @@ std::string CmdContext::joinWords (const std::vector & words, unsig for (unsigned int i = from; i < to; ++i) { if (i > from) - value += " "; + value += ' '; value += words[i]; } @@ -163,7 +163,7 @@ void CmdContext::defineContext (const std::vector & words, std::str if (!success) throw format (STRING_CMD_CONTEXT_DEF_FAIL, words[1]); - out << format (STRING_CMD_CONTEXT_DEF_SUCC, words[1]) << "\n"; + out << format (STRING_CMD_CONTEXT_DEF_SUCC, words[1]) << '\n'; } else throw std::string (STRING_CMD_CONTEXT_DEF_USAG); @@ -197,7 +197,7 @@ void CmdContext::deleteContext (const std::vector & words, std::str if (rc != 0) throw format (STRING_CMD_CONTEXT_DEL_FAIL, words[1]); - out << format (STRING_CMD_CONTEXT_DEL_SUCC, words[1]) << "\n"; + out << format (STRING_CMD_CONTEXT_DEL_SUCC, words[1]) << '\n'; } else throw std::string(STRING_CMD_CONTEXT_DEL_USAG); @@ -279,7 +279,7 @@ void CmdContext::setContext (const std::vector & words, std::string if (! success) throw format (STRING_CMD_CONTEXT_SET_FAIL, value); - out << format (STRING_CMD_CONTEXT_SET_SUCC, value) << "\n"; + out << format (STRING_CMD_CONTEXT_SET_SUCC, value) << '\n'; } //////////////////////////////////////////////////////////////////////////////// @@ -295,11 +295,11 @@ void CmdContext::showContext (std::stringstream& out) auto currentContext = context.config.get ("context"); if (currentContext == "") - out << STRING_CMD_CONTEXT_SHOW_EMPT << "\n"; + out << STRING_CMD_CONTEXT_SHOW_EMPT << '\n'; else { std::string currentFilter = context.config.get ("context." + currentContext); - out << format (STRING_CMD_CONTEXT_SHOW, currentContext, currentFilter) << "\n"; + out << format (STRING_CMD_CONTEXT_SHOW, currentContext, currentFilter) << '\n'; } } @@ -318,7 +318,7 @@ void CmdContext::unsetContext (std::stringstream& out) if (CmdConfig::unsetConfigVariable ("context", false)) throw std::string(STRING_CMD_CONTEXT_NON_FAIL); - out << STRING_CMD_CONTEXT_NON_SUCC << "\n"; + out << STRING_CMD_CONTEXT_NON_SUCC << '\n'; } //////////////////////////////////////////////////////////////////////////////// @@ -341,7 +341,7 @@ CmdCompletionContext::CmdCompletionContext () int CmdCompletionContext::execute (std::string& output) { for (auto& contet : CmdContext::getContexts ()) - output += contet + "\n"; + output += contet + '\n'; return 0; } diff --git a/src/commands/CmdCount.cpp b/src/commands/CmdCount.cpp index 275c8230f..a9e5d2043 100644 --- a/src/commands/CmdCount.cpp +++ b/src/commands/CmdCount.cpp @@ -62,7 +62,7 @@ int CmdCount::execute (std::string& output) if (task.getStatus () != Task::recurring) ++count; - output = format (count) + "\n"; + output = format (count) + '\n'; return 0; } diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index 6e55fcf0b..1c78dd2ca 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -225,7 +225,7 @@ int CmdCustom::execute (std::string& output) out << ", " << format (STRING_CMD_CUSTOM_TRUNCATED, maxlines - table_header); - out << "\n"; + out << '\n'; } } else diff --git a/src/commands/CmdDelete.cpp b/src/commands/CmdDelete.cpp index a67ecbdde..1697483b8 100644 --- a/src/commands/CmdDelete.cpp +++ b/src/commands/CmdDelete.cpp @@ -159,7 +159,7 @@ int CmdDelete::execute (std::string&) } else { - std::cout << STRING_CMD_DELETE_NO << "\n"; + std::cout << STRING_CMD_DELETE_NO << '\n'; rc = 1; if (_permission_quit) break; @@ -170,7 +170,7 @@ int CmdDelete::execute (std::string&) std::cout << format (STRING_CMD_DELETE_NOT_DEL, task.identifier (true), task.get ("description")) - << "\n"; + << '\n'; rc = 1; } } diff --git a/src/commands/CmdDenotate.cpp b/src/commands/CmdDenotate.cpp index f84c01ce5..1f958f8fa 100644 --- a/src/commands/CmdDenotate.cpp +++ b/src/commands/CmdDenotate.cpp @@ -140,7 +140,7 @@ int CmdDenotate::execute (std::string&) } else { - std::cout << STRING_CMD_DENO_NO << "\n"; + std::cout << STRING_CMD_DENO_NO << '\n'; rc = 1; if (_permission_quit) break; @@ -148,7 +148,7 @@ int CmdDenotate::execute (std::string&) } else { - std::cout << format (STRING_CMD_DENO_NOMATCH, pattern) << "\n"; + std::cout << format (STRING_CMD_DENO_NOMATCH, pattern) << '\n'; rc = 1; } } diff --git a/src/commands/CmdDiagnostics.cpp b/src/commands/CmdDiagnostics.cpp index a71fa5190..80ce794d5 100644 --- a/src/commands/CmdDiagnostics.cpp +++ b/src/commands/CmdDiagnostics.cpp @@ -75,19 +75,19 @@ int CmdDiagnostics::execute (std::string& output) bold = Color ("bold"); std::stringstream out; - out << "\n" + out << '\n' << bold.colorize (PACKAGE_STRING) - << "\n"; + << '\n'; out << " " << STRING_CMD_DIAG_PLATFORM << ": " << osName () << "\n\n"; // Compiler. out << bold.colorize (STRING_CMD_DIAG_COMPILER) - << "\n" + << '\n' #ifdef __VERSION__ << " " << STRING_CMD_DIAG_VERSION << ": " - << __VERSION__ << "\n" + << __VERSION__ << '\n' #endif << " " << STRING_CMD_DIAG_CAPS << ":" #ifdef __STDC__ @@ -116,7 +116,7 @@ int CmdDiagnostics::execute (std::string& output) << " +l" << 8 * sizeof (long) << " +vp" << 8 * sizeof (void*) << " +time_t" << 8 * sizeof (time_t) - << "\n"; + << '\n'; // Compiler compliance level. std::string compliance = "non-compliant"; @@ -129,20 +129,20 @@ int CmdDiagnostics::execute (std::string& output) else compliance = format (level); #endif - out << " " << STRING_CMD_DIAG_COMPLIANCE + out << ' ' << STRING_CMD_DIAG_COMPLIANCE << ": " << compliance << "\n\n"; out << bold.colorize (STRING_CMD_DIAG_FEATURES) - << "\n" + << '\n' // Build date. - << " " << STRING_CMD_DIAG_BUILT << ": " << __DATE__ << " " << __TIME__ << "\n" + << " " << STRING_CMD_DIAG_BUILT << ": " << __DATE__ << ' ' << __TIME__ << '\n' #ifdef HAVE_COMMIT - << " " << STRING_CMD_DIAG_COMMIT << ": " << COMMIT << "\n" + << " " << STRING_CMD_DIAG_COMMIT << ": " << COMMIT << '\n' #endif - << " CMake: " << CMAKE_VERSION << "\n"; + << " CMake: " << CMAKE_VERSION << '\n'; out << " libuuid: " #ifdef HAVE_UUID_UNPARSE_LOWER @@ -150,7 +150,7 @@ int CmdDiagnostics::execute (std::string& output) #else << "libuuid, no uuid_unparse_lower" #endif - << "\n"; + << '\n'; out << " libgnutls: " #ifdef HAVE_LIBGNUTLS @@ -162,7 +162,7 @@ int CmdDiagnostics::execute (std::string& output) #else << "n/a" #endif - << "\n"; + << '\n'; out << " Build type: " #ifdef CMAKE_BUILD_TYPE @@ -174,20 +174,20 @@ int CmdDiagnostics::execute (std::string& output) // Config: .taskrc found, readable, writable out << bold.colorize (STRING_CMD_DIAG_CONFIG) - << "\n" - << " File: " << context.config._original_file._data << " " + << '\n' + << " File: " << context.config._original_file._data << ' ' << (context.config._original_file.exists () ? STRING_CMD_DIAG_FOUND : STRING_CMD_DIAG_MISSING) - << ", " << context.config._original_file.size () << " " << "bytes" + << ", " << context.config._original_file.size () << ' ' << "bytes" << ", mode " << std::setbase (8) << context.config._original_file.mode () - << "\n"; + << '\n'; // Config: data.location found, readable, writable File location (context.config.get ("data.location")); - out << " Data: " << location._data << " " + out << " Data: " << location._data << ' ' << (location.exists () ? STRING_CMD_DIAG_FOUND : STRING_CMD_DIAG_MISSING) @@ -195,44 +195,44 @@ int CmdDiagnostics::execute (std::string& output) << ", mode " << std::setbase (8) << location.mode () - << "\n"; + << '\n'; char* env = getenv ("TASKRC"); if (env) out << " TASKRC: " << env - << "\n"; + << '\n'; env = getenv ("TASKDATA"); if (env) out << " TASKDATA: " << env - << "\n"; + << '\n'; out << " Locking: " << (context.config.getBoolean ("locking") ? STRING_CMD_DIAG_ENABLED : STRING_CMD_DIAG_DISABLED) - << "\n"; + << '\n'; out << " GC: " << (context.config.getBoolean ("gc") ? STRING_CMD_DIAG_ENABLED : STRING_CMD_DIAG_DISABLED) - << "\n"; + << '\n'; // Determine rc.editor/$EDITOR/$VISUAL. char* peditor; if (context.config.get ("editor") != "") - out << " rc.editor: " << context.config.get ("editor") << "\n"; + out << " rc.editor: " << context.config.get ("editor") << '\n'; else if ((peditor = getenv ("VISUAL")) != NULL) - out << " $VISUAL: " << peditor << "\n"; + out << " $VISUAL: " << peditor << '\n'; else if ((peditor = getenv ("EDITOR")) != NULL) - out << " $EDITOR: " << peditor << "\n"; + out << " $EDITOR: " << peditor << '\n'; out << " Server: " << context.config.get ("taskd.server") - << "\n"; + << '\n'; if (context.config.get ("taskd.ca") != "") out << " CA: " @@ -246,7 +246,7 @@ int CmdDiagnostics::execute (std::string& output) if (trust_value == "strict" || trust_value == "ignore hostname" || trust_value == "allow all") - out << " Trust: " << trust_value << "\n"; + out << " Trust: " << trust_value << '\n'; else out << " Trust: Bad value - see 'man taskrc'\n"; @@ -266,7 +266,7 @@ int CmdDiagnostics::execute (std::string& output) out << " Ciphers: " << context.config.get ("taskd.ciphers") - << "\n"; + << '\n'; // Get credentials, but mask out the key. std::string credentials = context.config.get ("taskd.credentials"); @@ -285,13 +285,13 @@ int CmdDiagnostics::execute (std::string& output) hookLocation += "hooks"; out << bold.colorize (STRING_CMD_DIAG_HOOKS) - << "\n" + << '\n' << " System: " << (context.config.getBoolean ("hooks") ? STRING_CMD_DIAG_HOOK_ENABLE : STRING_CMD_DIAG_HOOK_DISABLE) - << "\n" + << '\n' << " Location: " << static_cast (hookLocation) - << "\n"; + << '\n'; auto hooks = context.hooks.list (); if (hooks.size ()) @@ -323,13 +323,13 @@ int CmdDiagnostics::execute (std::string& output) out << std::left << name << format (" ({1})", STRING_CMD_DIAG_HOOK_EXEC) << (p.is_link () ? format (" ({1})", STRING_CMD_DIAG_HOOK_SYMLINK) : "") - << "\n"; + << '\n'; } } } if (! count) - out << "\n"; + out << '\n'; out << " Inactive: "; count = 0; @@ -356,22 +356,22 @@ int CmdDiagnostics::execute (std::string& output) name.substr (0, 9) == "on-modify" || name.substr (0, 9) == "on-launch" || name.substr (0, 7) == "on-exit") ? "" : format (" ({1})", STRING_CMD_DIAG_HOOK_NAME)) - << "\n"; + << '\n'; } } } if (! count) - out << "\n"; + out << '\n'; } else out << format (" ({1})\n", STRING_CMD_DIAG_NONE); - out << "\n"; + out << '\n'; // Verify UUIDs are all unique. out << bold.colorize (STRING_CMD_DIAG_TESTS) - << "\n"; + << '\n'; // Determine terminal details. const char* term = getenv ("TERM"); @@ -399,17 +399,17 @@ int CmdDiagnostics::execute (std::string& output) out << " Dups: " << format (STRING_CMD_DIAG_UUID_SCAN, all.size ()) - << "\n"; + << '\n'; if (dups.size ()) { for (auto& d : dups) - out << " " << format (STRING_CMD_DIAG_UUID_DUP, d) << "\n"; + out << " " << format (STRING_CMD_DIAG_UUID_DUP, d) << '\n'; } else { out << " " << STRING_CMD_DIAG_UUID_NO_DUP - << "\n"; + << '\n'; } @@ -418,7 +418,7 @@ int CmdDiagnostics::execute (std::string& output) bool noBrokenRefs = true; out << " Broken ref: " << format (STRING_CMD_DIAG_REF_SCAN, all.size ()) - << "\n"; + << '\n'; for (auto& task : all) { @@ -432,7 +432,7 @@ int CmdDiagnostics::execute (std::string& output) { out << " " << format (STRING_CMD_DIAG_MISS_DEP, task.get ("uuid"), uuid) - << "\n"; + << '\n'; noBrokenRefs = false; } } @@ -444,16 +444,16 @@ int CmdDiagnostics::execute (std::string& output) { out << " " << format (STRING_CMD_DIAG_MISS_PAR, task.get ("uuid"), parentUUID) - << "\n"; + << '\n'; noBrokenRefs = false; } } if (noBrokenRefs) out << " " << STRING_CMD_DIAG_REF_OK - << "\n"; + << '\n'; - out << "\n"; + out << '\n'; output = out.str (); return 0; } diff --git a/src/commands/CmdDone.cpp b/src/commands/CmdDone.cpp index 657949239..253ffb4b4 100644 --- a/src/commands/CmdDone.cpp +++ b/src/commands/CmdDone.cpp @@ -112,7 +112,7 @@ int CmdDone::execute (std::string&) } else { - std::cout << STRING_CMD_DONE_NO << "\n"; + std::cout << STRING_CMD_DONE_NO << '\n'; rc = 1; if (_permission_quit) break; @@ -123,7 +123,7 @@ int CmdDone::execute (std::string&) std::cout << format (STRING_CMD_DONE_NOTPEND, task.identifier (true), task.get ("description")) - << "\n"; + << '\n'; rc = 1; } } diff --git a/src/commands/CmdDuplicate.cpp b/src/commands/CmdDuplicate.cpp index 9f0cc84f7..350dacabc 100644 --- a/src/commands/CmdDuplicate.cpp +++ b/src/commands/CmdDuplicate.cpp @@ -89,7 +89,7 @@ int CmdDuplicate::execute (std::string&) dup.remove ("until"); dup.remove ("imask"); std::cout << format (STRING_CMD_DUPLICATE_NON_REC, task.identifier ()) - << "\n"; + << '\n'; } // When duplicating a parent task, create a new parent task. @@ -97,7 +97,7 @@ int CmdDuplicate::execute (std::string&) { dup.remove ("mask"); std::cout << format (STRING_CMD_DUPLICATE_REC, task.identifier ()) - << "\n"; + << '\n'; } dup.setStatus (Task::pending); // Does not inherit status. @@ -118,18 +118,18 @@ int CmdDuplicate::execute (std::string&) if (context.verbose ("new-id") && (status == Task::pending || status == Task::waiting)) - std::cout << format (STRING_CMD_ADD_FEEDBACK, dup.id) + "\n"; + std::cout << format (STRING_CMD_ADD_FEEDBACK, dup.id) + '\n'; else if (context.verbose ("new-uuid") && status != Task::recurring) - std::cout << format (STRING_CMD_ADD_FEEDBACK, dup.get ("uuid")) + "\n"; + std::cout << format (STRING_CMD_ADD_FEEDBACK, dup.get ("uuid")) + '\n'; if (context.verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task); } else { - std::cout << STRING_CMD_DUPLICATE_NO << "\n"; + std::cout << STRING_CMD_DUPLICATE_NO << '\n'; rc = 1; if (_permission_quit) break; diff --git a/src/commands/CmdEdit.cpp b/src/commands/CmdEdit.cpp index 82265887a..36d1d8093 100644 --- a/src/commands/CmdEdit.cpp +++ b/src/commands/CmdEdit.cpp @@ -102,7 +102,7 @@ std::string CmdEdit::findValue ( auto found = text.find (name); if (found != std::string::npos) { - auto eol = text.find ("\n", found + 1); + auto eol = text.find ('\n', found + 1); if (eol != std::string::npos) { std::string value = text.substr ( @@ -149,7 +149,7 @@ std::vector CmdEdit::findValues ( found = text.find (name, found + 1); if (found != std::string::npos) { - auto eol = text.find ("\n", found + 1); + auto eol = text.find ('\n', found + 1); if (eol != std::string::npos) { std::string value = text.substr ( @@ -203,30 +203,30 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) bool verbose = context.verbose ("edit"); if (verbose) - before << "# " << STRING_EDIT_HEADER_1 << "\n" - << "# " << STRING_EDIT_HEADER_2 << "\n" - << "# " << STRING_EDIT_HEADER_3 << "\n" - << "# " << STRING_EDIT_HEADER_4 << "\n" - << "# " << STRING_EDIT_HEADER_5 << "\n" - << "# " << STRING_EDIT_HEADER_6 << "\n" + before << "# " << STRING_EDIT_HEADER_1 << '\n' + << "# " << STRING_EDIT_HEADER_2 << '\n' + << "# " << STRING_EDIT_HEADER_3 << '\n' + << "# " << STRING_EDIT_HEADER_4 << '\n' + << "# " << STRING_EDIT_HEADER_5 << '\n' + << "# " << STRING_EDIT_HEADER_6 << '\n' << "#\n" - << "# " << STRING_EDIT_HEADER_7 << "\n" - << "# " << STRING_EDIT_HEADER_8 << "\n" - << "# " << STRING_EDIT_HEADER_9 << "\n" + << "# " << STRING_EDIT_HEADER_7 << '\n' + << "# " << STRING_EDIT_HEADER_8 << '\n' + << "# " << STRING_EDIT_HEADER_9 << '\n' << "#\n" - << "# " << STRING_EDIT_HEADER_10 << "\n" - << "# " << STRING_EDIT_HEADER_11 << "\n" - << "# " << STRING_EDIT_HEADER_12 << "\n" + << "# " << STRING_EDIT_HEADER_10 << '\n' + << "# " << STRING_EDIT_HEADER_11 << '\n' + << "# " << STRING_EDIT_HEADER_12 << '\n' << "#\n"; - before << "# " << STRING_EDIT_TABLE_HEADER_1 << "\n" - << "# " << STRING_EDIT_TABLE_HEADER_2 << "\n" - << "# ID: " << task.id << "\n" - << "# UUID: " << task.get ("uuid") << "\n" - << "# Status: " << Lexer::ucFirst (Task::statusToText (task.getStatus ())) << "\n" - << "# Mask: " << task.get ("mask") << "\n" - << "# iMask: " << task.get ("imask") << "\n" - << " Project: " << task.get ("project") << "\n"; + before << "# " << STRING_EDIT_TABLE_HEADER_1 << '\n' + << "# " << STRING_EDIT_TABLE_HEADER_2 << '\n' + << "# ID: " << task.id << '\n' + << "# UUID: " << task.get ("uuid") << '\n' + << "# Status: " << Lexer::ucFirst (Task::statusToText (task.getStatus ())) << '\n' + << "# Mask: " << task.get ("mask") << '\n' + << "# iMask: " << task.get ("imask") << '\n' + << " Project: " << task.get ("project") << '\n'; std::vector tags; task.getTags (tags); @@ -234,25 +234,25 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) join (allTags, " ", tags); if (verbose) - before << "# " << STRING_EDIT_TAG_SEP << "\n"; + before << "# " << STRING_EDIT_TAG_SEP << '\n'; - before << " Tags: " << allTags << "\n" - << " Description: " << task.get ("description") << "\n" - << " Created: " << formatDate (task, "entry", dateformat) << "\n" - << " Started: " << formatDate (task, "start", dateformat) << "\n" - << " Ended: " << formatDate (task, "end", dateformat) << "\n" - << " Scheduled: " << formatDate (task, "scheduled", dateformat) << "\n" - << " Due: " << formatDate (task, "due", dateformat) << "\n" - << " Until: " << formatDate (task, "until", dateformat) << "\n" - << " Recur: " << task.get ("recur") << "\n" - << " Wait until: " << formatDate (task, "wait", dateformat) << "\n" - << "# Modified: " << formatDate (task, "modified", dateformat) << "\n" - << " Parent: " << task.get ("parent") << "\n"; + before << " Tags: " << allTags << '\n' + << " Description: " << task.get ("description") << '\n' + << " Created: " << formatDate (task, "entry", dateformat) << '\n' + << " Started: " << formatDate (task, "start", dateformat) << '\n' + << " Ended: " << formatDate (task, "end", dateformat) << '\n' + << " Scheduled: " << formatDate (task, "scheduled", dateformat) << '\n' + << " Due: " << formatDate (task, "due", dateformat) << '\n' + << " Until: " << formatDate (task, "until", dateformat) << '\n' + << " Recur: " << task.get ("recur") << '\n' + << " Wait until: " << formatDate (task, "wait", dateformat) << '\n' + << "# Modified: " << formatDate (task, "modified", dateformat) << '\n' + << " Parent: " << task.get ("parent") << '\n'; if (verbose) - before << "# " << STRING_EDIT_HEADER_13 << "\n" - << "# " << STRING_EDIT_HEADER_14 << "\n" - << "# " << STRING_EDIT_HEADER_15 << "\n"; + before << "# " << STRING_EDIT_HEADER_13 << '\n' + << "# " << STRING_EDIT_HEADER_14 << '\n' + << "# " << STRING_EDIT_HEADER_15 << '\n'; std::map annotations; task.getAnnotations (annotations); @@ -260,7 +260,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) { ISO8601d dt (strtol (anno.first.substr (11).c_str (), NULL, 10)); before << " Annotation: " << dt.toString (dateformat) - << " -- " << json::encode (anno.second) << "\n"; + << " -- " << json::encode (anno.second) << '\n'; } ISO8601d now; @@ -285,9 +285,9 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) } if (verbose) - before << "# " << STRING_EDIT_DEP_SEP << "\n"; + before << "# " << STRING_EDIT_DEP_SEP << '\n'; - before << " Dependencies: " << allDeps.str () << "\n"; + before << " Dependencies: " << allDeps.str () << '\n'; // UDAs std::vector udas; @@ -297,7 +297,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) if (udas.size ()) { - before << "# " << STRING_EDIT_UDA_SEP << "\n"; + before << "# " << STRING_EDIT_UDA_SEP << '\n'; std::sort (udas.begin (), udas.end ()); for (auto& uda : udas) { @@ -307,12 +307,12 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) padding = std::string (pad, ' '); std::string type = context.config.get ("uda." + uda + ".type"); - if (type == "string" || type == "numeric") - before << " UDA " << uda << ": " << padding << task.get (uda) << "\n"; + if (type == "string" || type == "numeric") + 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'; } } @@ -322,7 +322,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) if (orphans.size ()) { - before << "# " << STRING_EDIT_UDA_ORPHAN_SEP << "\n"; + before << "# " << STRING_EDIT_UDA_ORPHAN_SEP << '\n'; std::sort (orphans.begin (), orphans.end ()); for (auto& orphan : orphans) { @@ -331,11 +331,11 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) 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'; } } - before << "# " << STRING_EDIT_END << "\n"; + before << "# " << STRING_EDIT_END << '\n'; return before.str (); } @@ -633,7 +633,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { found += 14; // Length of "\n Annotation:". - auto eol = after.find ("\n", found + 1); + auto eol = after.find ('\n', found + 1); if (eol != std::string::npos) { std::string value = Lexer::trim (after.substr ( @@ -797,22 +797,22 @@ CmdEdit::editResult CmdEdit::editFile (Task& task) if (editor == "") editor = "vi"; // Complete the command line. - editor += " "; + editor += ' '; editor += "\"" + file.str () + "\""; ARE_THESE_REALLY_HARMFUL: bool changes = false; // No changes made. // Launch the editor. - std::cout << format (STRING_EDIT_LAUNCHING, editor) << "\n"; + std::cout << format (STRING_EDIT_LAUNCHING, editor) << '\n'; int exitcode = system (editor.c_str ()); if (0 == exitcode) - std::cout << STRING_EDIT_COMPLETE << "\n"; + std::cout << STRING_EDIT_COMPLETE << '\n'; else { - std::cout << format (STRING_EDIT_FAILED, exitcode) << "\n"; + std::cout << format (STRING_EDIT_FAILED, exitcode) << '\n'; if (-1 == exitcode) - std::cout << std::strerror (errno) << "\n"; + std::cout << std::strerror (errno) << '\n'; return CmdEdit::editResult::error; } @@ -824,7 +824,7 @@ ARE_THESE_REALLY_HARMFUL: // if changes were made. if (before_orig != after) { - std::cout << STRING_EDIT_CHANGES << "\n"; + std::cout << STRING_EDIT_CHANGES << '\n'; std::string problem = ""; bool oops = false; @@ -841,7 +841,7 @@ ARE_THESE_REALLY_HARMFUL: if (oops) { - std::cerr << STRING_ERROR_PREFIX << problem << "\n"; + std::cerr << STRING_ERROR_PREFIX << problem << '\n'; // Preserve the edits. before = after; @@ -855,7 +855,7 @@ ARE_THESE_REALLY_HARMFUL: } else { - std::cout << STRING_EDIT_NO_CHANGES << "\n"; + std::cout << STRING_EDIT_NO_CHANGES << '\n'; changes = false; } diff --git a/src/commands/CmdExport.cpp b/src/commands/CmdExport.cpp index 2bffb7861..c406bf2b8 100644 --- a/src/commands/CmdExport.cpp +++ b/src/commands/CmdExport.cpp @@ -85,7 +85,7 @@ int CmdExport::execute (std::string& output) { if (json_array) output += ","; - output += "\n"; + output += '\n'; } output += task.composeJSON (true); @@ -96,7 +96,7 @@ int CmdExport::execute (std::string& output) } if (filtered.size ()) - output += "\n"; + output += '\n'; if (json_array) output += "]\n"; diff --git a/src/commands/CmdGet.cpp b/src/commands/CmdGet.cpp index 83e374f33..363574a66 100644 --- a/src/commands/CmdGet.cpp +++ b/src/commands/CmdGet.cpp @@ -91,7 +91,7 @@ int CmdGet::execute (std::string& output) throw std::string (STRING_CMD_GET_NO_DOM); join (output, " ", results); - output += "\n"; + output += '\n'; return 0; } diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index 371c0801a..de0d9af85 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -32,7 +32,6 @@ #include #include #include -#include // TODO Remove extern Context context; @@ -57,13 +56,13 @@ int CmdHelp::execute (std::string& output) { auto words = context.cli2.getWords (); if (words.size () == 1 && closeEnough ("usage", words[0])) - output = "\n" + output = '\n' + composeUsage () - + "\n"; + + '\n'; else - output = "\n" + output = '\n' + composeUsage () - + "\n" + + '\n' + STRING_CMD_HELP_TEXT; return 0; diff --git a/src/commands/CmdHistory.cpp b/src/commands/CmdHistory.cpp index bca8a7259..2cec28d86 100644 --- a/src/commands/CmdHistory.cpp +++ b/src/commands/CmdHistory.cpp @@ -174,7 +174,7 @@ int CmdHistoryMonthly::execute (std::string& output) if (view.rows ()) { row = view.addRow (); - view.set (row, 0, " "); + view.set (row, 0, ' '); row = view.addRow (); Color row_color; @@ -192,7 +192,7 @@ int CmdHistoryMonthly::execute (std::string& output) if (view.rows ()) out << optionalBlankLine () << view.render () - << "\n"; + << '\n'; else { context.footnote (STRING_FEEDBACK_NO_TASKS); @@ -354,7 +354,7 @@ int CmdHistoryAnnual::execute (std::string& output) if (view.rows ()) out << optionalBlankLine () << view.render () - << "\n"; + << '\n'; else { context.footnote (STRING_FEEDBACK_NO_TASKS); @@ -498,7 +498,7 @@ int CmdGHistoryMonthly::execute (std::string& output) { aBar = format (addedGroup[i.first]); while (aBar.length () < addedBar) - aBar = " " + aBar; + aBar = ' ' + aBar; } std::string cBar = ""; @@ -506,7 +506,7 @@ int CmdGHistoryMonthly::execute (std::string& output) { cBar = format (completedGroup[i.first]); while (cBar.length () < completedBar) - cBar = " " + cBar; + cBar = ' ' + cBar; } std::string dBar = ""; @@ -514,7 +514,7 @@ int CmdGHistoryMonthly::execute (std::string& output) { dBar = format (deletedGroup[i.first]); while (dBar.length () < deletedBar) - dBar = " " + dBar; + dBar = ' ' + dBar; } bar += std::string (leftOffset - aBar.length (), ' '); @@ -542,7 +542,7 @@ int CmdGHistoryMonthly::execute (std::string& output) { out << optionalBlankLine () << view.render () - << "\n"; + << '\n'; if (context.color ()) out << format (STRING_CMD_HISTORY_LEGEND, @@ -550,10 +550,10 @@ int CmdGHistoryMonthly::execute (std::string& output) color_done.colorize (STRING_CMD_HISTORY_COMP), color_delete.colorize (STRING_CMD_HISTORY_DEL)) << optionalBlankLine () - << "\n"; + << '\n'; else out << STRING_CMD_HISTORY_LEGEND_A - << "\n"; + << '\n'; } else { @@ -696,7 +696,7 @@ int CmdGHistoryAnnual::execute (std::string& output) { aBar = format (addedGroup[i.first]); while (aBar.length () < addedBar) - aBar = " " + aBar; + aBar = ' ' + aBar; } std::string cBar = ""; @@ -704,7 +704,7 @@ int CmdGHistoryAnnual::execute (std::string& output) { cBar = format (completedGroup[i.first]); while (cBar.length () < completedBar) - cBar = " " + cBar; + cBar = ' ' + cBar; } std::string dBar = ""; @@ -712,7 +712,7 @@ int CmdGHistoryAnnual::execute (std::string& output) { dBar = format (deletedGroup[i.first]); while (dBar.length () < deletedBar) - dBar = " " + dBar; + dBar = ' ' + dBar; } bar += std::string (leftOffset - aBar.length (), ' '); @@ -739,7 +739,7 @@ int CmdGHistoryAnnual::execute (std::string& output) { out << optionalBlankLine () << view.render () - << "\n"; + << '\n'; if (context.color ()) out << format (STRING_CMD_HISTORY_LEGEND, @@ -747,10 +747,10 @@ int CmdGHistoryAnnual::execute (std::string& output) color_done.colorize (STRING_CMD_HISTORY_COMP), color_delete.colorize (STRING_CMD_HISTORY_DEL)) << optionalBlankLine () - << "\n"; + << '\n'; else out << STRING_CMD_HISTORY_LEGEND_A - << "\n"; + << '\n'; } else { diff --git a/src/commands/CmdIDs.cpp b/src/commands/CmdIDs.cpp index b8cc6021a..abb84eecd 100644 --- a/src/commands/CmdIDs.cpp +++ b/src/commands/CmdIDs.cpp @@ -70,7 +70,7 @@ int CmdIDs::execute (std::string& output) ids.push_back (task.id); std::sort (ids.begin (), ids.end ()); - output = compressIds (ids) + "\n"; + output = compressIds (ids) + '\n'; context.headers.clear (); return 0; @@ -100,7 +100,7 @@ std::string CmdIDs::compressIds (const std::vector & ids) if (i + 1 == ids.size ()) { if (result.str ().length ()) - result << " "; + result << ' '; if (range_start < range_end) result << ids[range_start] << "-" << ids[range_end]; @@ -116,7 +116,7 @@ std::string CmdIDs::compressIds (const std::vector & ids) else { if (result.str ().length ()) - result << " "; + result << ' '; if (range_start < range_end) result << ids[range_start] << "-" << ids[range_end]; @@ -164,7 +164,7 @@ int CmdCompletionIds::execute (std::string& output) std::sort (ids.begin (), ids.end ()); join (output, "\n", ids); - output += "\n"; + output += '\n'; context.headers.clear (); return 0; @@ -200,9 +200,9 @@ int CmdZshCompletionIds::execute (std::string& output) if (task.getStatus () != Task::deleted && task.getStatus () != Task::completed) out << task.id - << ":" + << ':' << str_replace(task.get ("description"), ":", zshColonReplacement) - << "\n"; + << '\n'; output = out.str (); @@ -241,7 +241,7 @@ int CmdUUIDs::execute (std::string& output) std::sort (uuids.begin (), uuids.end ()); join (output, " ", uuids); - output += "\n"; + output += '\n'; context.headers.clear (); return 0; @@ -278,7 +278,7 @@ int CmdCompletionUuids::execute (std::string& output) std::sort (uuids.begin (), uuids.end ()); join (output, "\n", uuids); - output += "\n"; + output += '\n'; context.headers.clear (); return 0; @@ -314,7 +314,7 @@ int CmdZshCompletionUuids::execute (std::string& output) out << task.get ("uuid") << ":" << str_replace (task.get ("description"), ":", zshColonReplacement) - << "\n"; + << '\n'; output = out.str (); diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index b8687f3b4..ae893ac51 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -64,12 +64,12 @@ int CmdImport::execute (std::string&) std::vector words = context.cli2.getWords (); if (! words.size () || (words.size () == 1 && words[0] == "-")) { - std::cout << format (STRING_CMD_IMPORT_FILE, "STDIN") << "\n"; + std::cout << format (STRING_CMD_IMPORT_FILE, "STDIN") << '\n'; std::string json; std::string line; while (std::getline (std::cin, line)) - json += line + "\n"; + json += line + '\n'; if (nontrivial (json)) count = import (json); @@ -83,7 +83,7 @@ int CmdImport::execute (std::string&) if (! incoming.exists ()) throw format (STRING_CMD_IMPORT_MISSING, word); - std::cout << format (STRING_CMD_IMPORT_FILE, word) << "\n"; + std::cout << format (STRING_CMD_IMPORT_FILE, word) << '\n'; // Load the file. std::string json; @@ -224,9 +224,9 @@ void CmdImport::importSingleTask (json::object* obj) } std::cout << task.get ("uuid") - << " " + << ' ' << task.get ("description") - << "\n"; + << '\n'; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index 92445a58f..13b603398 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -130,10 +130,10 @@ int CmdInfo::execute (std::string& output) std::map annotations; task.getAnnotations (annotations); for (auto& anno : annotations) - description += "\n" + description += '\n' + std::string (indent, ' ') + ISO8601d (anno.first.substr (11)).toString (dateformatanno) - + " " + + ' ' + anno.second; row = view.addRow (); @@ -161,7 +161,7 @@ int CmdInfo::execute (std::string& output) { std::stringstream message; for (auto& block : blocked) - message << block.id << " " << block.get ("description") << "\n"; + message << block.id << ' ' << block.get ("description") << '\n'; row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_BLOCKED); @@ -177,7 +177,7 @@ int CmdInfo::execute (std::string& output) { std::stringstream message; for (auto& block : blocking) - message << block.id << " " << block.get ("description") << "\n"; + message << block.id << ' ' << block.get ("description") << '\n'; row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_BLOCKING); @@ -558,15 +558,15 @@ int CmdInfo::execute (std::string& output) out << optionalBlankLine () << view.render () - << "\n"; + << '\n'; if (urgencyDetails.rows () > 0) out << urgencyDetails.render () - << "\n"; + << '\n'; if (journal.rows () > 0) out << journal.render () - << "\n"; + << '\n'; } output = out.str (); diff --git a/src/commands/CmdLog.cpp b/src/commands/CmdLog.cpp index 7e0816c22..886507578 100644 --- a/src/commands/CmdLog.cpp +++ b/src/commands/CmdLog.cpp @@ -72,7 +72,7 @@ int CmdLog::execute (std::string& output) context.footnote (onProjectChange (task)); if (context.verbose ("new-uuid")) - output = format (STRING_CMD_LOG_LOGGED, task.get ("uuid")) + "\n"; + output = format (STRING_CMD_LOG_LOGGED, task.get ("uuid")) + '\n'; return 0; } diff --git a/src/commands/CmdLogo.cpp b/src/commands/CmdLogo.cpp index 744c7e641..1c25fbc06 100644 --- a/src/commands/CmdLogo.cpp +++ b/src/commands/CmdLogo.cpp @@ -127,7 +127,7 @@ int CmdLogo::execute (std::string& output) } } - output += "\n"; + output += '\n'; } output += optionalBlankLine (); diff --git a/src/commands/CmdModify.cpp b/src/commands/CmdModify.cpp index d2a71d3ff..db203e180 100644 --- a/src/commands/CmdModify.cpp +++ b/src/commands/CmdModify.cpp @@ -92,7 +92,7 @@ int CmdModify::execute (std::string&) } else { - std::cout << STRING_CMD_MODIFY_NO << "\n"; + std::cout << STRING_CMD_MODIFY_NO << '\n'; rc = 1; if (_permission_quit) break; diff --git a/src/commands/CmdPrepend.cpp b/src/commands/CmdPrepend.cpp index 4e2b04ce2..c0ead57f1 100644 --- a/src/commands/CmdPrepend.cpp +++ b/src/commands/CmdPrepend.cpp @@ -118,7 +118,7 @@ int CmdPrepend::execute (std::string&) } else { - std::cout << STRING_CMD_PREPEND_NO << "\n"; + std::cout << STRING_CMD_PREPEND_NO << '\n'; rc = 1; if (_permission_quit) break; diff --git a/src/commands/CmdProjects.cpp b/src/commands/CmdProjects.cpp index 6b632a3ba..b1ecb8a25 100644 --- a/src/commands/CmdProjects.cpp +++ b/src/commands/CmdProjects.cpp @@ -147,15 +147,15 @@ int CmdProjects::execute (std::string& output) << (number_projects == 1 ? format (STRING_CMD_PROJECTS_SUMMARY, number_projects) : format (STRING_CMD_PROJECTS_SUMMARY2, number_projects)) - << " " + << ' ' << (quantity == 1 ? format (STRING_CMD_PROJECTS_TASK, quantity) : format (STRING_CMD_PROJECTS_TASKS, quantity)) - << "\n"; + << '\n'; } else { - out << STRING_CMD_PROJECTS_NO << "\n"; + out << STRING_CMD_PROJECTS_NO << '\n'; rc = 1; } @@ -203,7 +203,7 @@ int CmdCompletionProjects::execute (std::string& output) for (auto& project : unique) if (project.first.length ()) - output += project.first + "\n"; + output += project.first + '\n'; return 0; } diff --git a/src/commands/CmdReports.cpp b/src/commands/CmdReports.cpp index 6cb5ae1e5..4474f96bd 100644 --- a/src/commands/CmdReports.cpp +++ b/src/commands/CmdReports.cpp @@ -111,7 +111,7 @@ int CmdReports::execute (std::string& output) << view.render () << optionalBlankLine () << format (STRING_CMD_REPORTS_SUMMARY, reports.size ()) - << "\n"; + << '\n'; output = out.str (); return 0; diff --git a/src/commands/CmdShow.cpp b/src/commands/CmdShow.cpp index cfda33f4b..56d848ac5 100644 --- a/src/commands/CmdShow.cpp +++ b/src/commands/CmdShow.cpp @@ -222,7 +222,7 @@ int CmdShow::execute (std::string& output) { // 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 @@ -320,14 +320,14 @@ int CmdShow::execute (std::string& output) } } - out << "\n" + out << '\n' << view.render () << (view.rows () == 0 ? STRING_CMD_SHOW_NONE : "") << (view.rows () == 0 ? "\n\n" : "\n"); if (issue_warning) { - out << STRING_CMD_SHOW_DIFFER << "\n"; + out << STRING_CMD_SHOW_DIFFER << '\n'; if (context.color () && warning.nontrivial ()) out << " " @@ -338,13 +338,13 @@ int CmdShow::execute (std::string& output) // Display the unrecognized variables. if (issue_error) { - out << STRING_CMD_SHOW_UNREC << "\n"; + out << STRING_CMD_SHOW_UNREC << '\n'; for (auto& i : unrecognized) - out << " " << i << "\n"; + out << " " << i << '\n'; if (context.color () && error.nontrivial ()) - out << "\n" << format (STRING_CMD_SHOW_DIFFER_COLOR, error.colorize ("color")); + out << '\n' << format (STRING_CMD_SHOW_DIFFER_COLOR, error.colorize ("color")); out << "\n\n"; } @@ -361,7 +361,7 @@ int CmdShow::execute (std::string& output) calendardetails != "sparse" && calendardetails != "none") out << format (STRING_CMD_SHOW_CONFIG_ERROR, "calendar.details", calendardetails) - << "\n"; + << '\n'; // Check for bad values in rc.calendar.holidays. std::string calendarholidays = context.config.get ("calendar.holidays"); @@ -369,14 +369,14 @@ int CmdShow::execute (std::string& output) calendarholidays != "sparse" && calendarholidays != "none") out << format (STRING_CMD_SHOW_CONFIG_ERROR, "calendar.holidays", calendarholidays) - << "\n"; + << '\n'; // Verify installation. This is mentioned in the documentation as the way // to ensure everything is properly installed. if (context.config.size () == 0) { - out << STRING_CMD_SHOW_EMPTY << "\n"; + out << STRING_CMD_SHOW_EMPTY << '\n'; rc = 1; } else @@ -384,10 +384,10 @@ int CmdShow::execute (std::string& output) Directory location (context.config.get ("data.location")); if (location._data == "") - out << STRING_CMD_SHOW_NO_LOCATION << "\n"; + out << STRING_CMD_SHOW_NO_LOCATION << '\n'; if (! location.exists ()) - out << STRING_CMD_SHOW_LOC_EXIST << "\n"; + out << STRING_CMD_SHOW_LOC_EXIST << '\n'; } output = out.str (); @@ -418,7 +418,7 @@ int CmdShowRaw::execute (std::string& output) // Display them all. std::stringstream out; for (auto& i : all) - out << i << '=' << context.config.get (i) << "\n"; + out << i << '=' << context.config.get (i) << '\n'; output = out.str (); return 0; diff --git a/src/commands/CmdStart.cpp b/src/commands/CmdStart.cpp index dbad4c2d0..34f2df484 100644 --- a/src/commands/CmdStart.cpp +++ b/src/commands/CmdStart.cpp @@ -109,7 +109,7 @@ int CmdStart::execute (std::string&) } else { - std::cout << STRING_CMD_START_NO << "\n"; + std::cout << STRING_CMD_START_NO << '\n'; rc = 1; if (_permission_quit) break; @@ -120,7 +120,7 @@ int CmdStart::execute (std::string&) std::cout << format (STRING_CMD_START_ALREADY, task.id, task.get ("description")) - << "\n"; + << '\n'; rc = 1; } } diff --git a/src/commands/CmdStop.cpp b/src/commands/CmdStop.cpp index 7ce117cd5..40dc5e33a 100644 --- a/src/commands/CmdStop.cpp +++ b/src/commands/CmdStop.cpp @@ -99,7 +99,7 @@ int CmdStop::execute (std::string&) } else { - std::cout << STRING_CMD_STOP_NO << "\n"; + std::cout << STRING_CMD_STOP_NO << '\n'; rc = 1; if (_permission_quit) break; @@ -110,7 +110,7 @@ int CmdStop::execute (std::string&) std::cout << format (STRING_CMD_STOP_ALREADY, task.identifier (true), task.get ("description")) - << "\n"; + << '\n'; rc = 1; } } diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index 04e06ce4b..99783e2c5 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -212,11 +212,11 @@ int CmdSummary::execute (std::string& output) << view.render () << optionalBlankLine (); - out << format (STRING_CMD_PROJECTS_SUMMARY2, view.rows ()) << "\n"; + out << format (STRING_CMD_PROJECTS_SUMMARY2, view.rows ()) << '\n'; } else { - out << STRING_CMD_PROJECTS_NO << "\n"; + out << STRING_CMD_PROJECTS_NO << '\n'; rc = 1; } diff --git a/src/commands/CmdSync.cpp b/src/commands/CmdSync.cpp index c791a6928..52d425761 100644 --- a/src/commands/CmdSync.cpp +++ b/src/commands/CmdSync.cpp @@ -138,7 +138,7 @@ int CmdSync::execute (std::string& output) auto all_tasks = context.tdb2.all_tasks (); for (auto& i : all_tasks) { - payload += i.composeJSON () + "\n"; + payload += i.composeJSON () + '\n'; ++upload_count; } } @@ -150,7 +150,7 @@ int CmdSync::execute (std::string& output) if (i[0] == '{') ++upload_count; - payload += i + "\n"; + payload += i + '\n'; } } @@ -172,7 +172,7 @@ int CmdSync::execute (std::string& output) if (context.verbose ("sync")) out << format (STRING_CMD_SYNC_PROGRESS, connection) - << "\n"; + << '\n'; // Ignore harmful signals. signal (SIGHUP, SIG_IGN); @@ -227,7 +227,7 @@ int CmdSync::execute (std::string& output) format (STRING_CMD_SYNC_MOD, uuid, from_server.get ("description"))) - << "\n"; + << '\n'; context.tdb2.modify (from_server, false); } else @@ -238,7 +238,7 @@ int CmdSync::execute (std::string& output) format (STRING_CMD_SYNC_ADD, uuid, from_server.get ("description"))) - << "\n"; + << '\n'; context.tdb2.add (from_server, false); } } @@ -259,7 +259,7 @@ int CmdSync::execute (std::string& output) context.tdb2.backlog._file.truncate (); context.tdb2.backlog.clear_tasks (); context.tdb2.backlog.clear_lines (); - context.tdb2.backlog.add_line (sync_key + "\n"); + context.tdb2.backlog.add_line (sync_key + '\n'); // Present a clear status message. if (upload_count == 0 && download_count == 0) @@ -326,7 +326,7 @@ int CmdSync::execute (std::string& output) } if (context.verbose ("sync")) - out << "\n"; + out << '\n'; output = out.str (); // Restore signal handling. @@ -373,7 +373,7 @@ bool CmdSync::send ( client.ciphers (context.config.get ("taskd.ciphers")); client.init (ca, certificate, key); client.connect (server, port); - client.send (request.serialize () + "\n"); + client.send (request.serialize () + '\n'); std::string incoming; client.recv (incoming); diff --git a/src/commands/CmdTags.cpp b/src/commands/CmdTags.cpp index 0f2fc82e6..95eedbb9a 100644 --- a/src/commands/CmdTags.cpp +++ b/src/commands/CmdTags.cpp @@ -134,7 +134,7 @@ int CmdTags::execute (std::string& output) else context.footnote (format (STRING_FEEDBACK_TASKS_PLURAL, quantity)); - out << "\n"; + out << '\n'; } else { @@ -224,7 +224,7 @@ int CmdCompletionTags::execute (std::string& output) std::stringstream out; for (auto& it : unique) - out << it.first << "\n"; + out << it.first << '\n'; output = out.str (); return 0; diff --git a/src/commands/CmdTimesheet.cpp b/src/commands/CmdTimesheet.cpp index f2e5ae752..15d25ba55 100644 --- a/src/commands/CmdTimesheet.cpp +++ b/src/commands/CmdTimesheet.cpp @@ -97,9 +97,9 @@ int CmdTimesheet::execute (std::string& output) if (context.color ()) bold = Color ("bold"); - out << "\n" + out << '\n' << bold.colorize (title) - << "\n"; + << '\n'; // Render the completed table. ViewText completed; @@ -145,10 +145,10 @@ int CmdTimesheet::execute (std::string& output) std::map annotations; task.getAnnotations (annotations); for (auto& ann : annotations) - description += "\n" + description += '\n' + std::string (indent, ' ') + ISO8601d (ann.first.substr (11)).toString (context.config.get ("dateformat")) - + " " + + ' ' + ann.second; completed.set (row, 3, description, c); @@ -156,11 +156,11 @@ int CmdTimesheet::execute (std::string& output) } } - out << " " << format (STRING_CMD_TIMESHEET_DONE, completed.rows ()) << "\n"; + out << " " << format (STRING_CMD_TIMESHEET_DONE, completed.rows ()) << '\n'; if (completed.rows ()) out << completed.render () - << "\n"; + << '\n'; // Now render the started table. ViewText started; @@ -201,10 +201,10 @@ int CmdTimesheet::execute (std::string& output) std::map annotations; task.getAnnotations (annotations); for (auto& ann : annotations) - description += "\n" + description += '\n' + std::string (indent, ' ') + ISO8601d (ann.first.substr (11)).toString (context.config.get ("dateformat")) - + " " + + ' ' + ann.second; started.set (row, 3, description, c); @@ -212,7 +212,7 @@ int CmdTimesheet::execute (std::string& output) } } - out << " " << format (STRING_CMD_TIMESHEET_STARTED, started.rows ()) << "\n"; + out << " " << format (STRING_CMD_TIMESHEET_STARTED, started.rows ()) << '\n'; if (started.rows ()) out << started.render () diff --git a/src/commands/CmdUDAs.cpp b/src/commands/CmdUDAs.cpp index bb057aacc..e3d8a0b0d 100644 --- a/src/commands/CmdUDAs.cpp +++ b/src/commands/CmdUDAs.cpp @@ -128,11 +128,11 @@ int CmdUDAs::execute (std::string& output) << (udas.size () == 1 ? format (STRING_CMD_UDAS_SUMMARY, udas.size ()) : format (STRING_CMD_UDAS_SUMMARY2, udas.size ())) - << "\n"; + << '\n'; } else { - out << STRING_CMD_UDAS_NO << "\n"; + out << STRING_CMD_UDAS_NO << '\n'; rc = 1; } @@ -173,7 +173,7 @@ int CmdUDAs::execute (std::string& output) << (udas.size () == 1 ? format (STRING_CMD_UDAS_ORPHAN, orphans.size ()) : format (STRING_CMD_UDAS_ORPHANS, orphans.size ())) - << "\n"; + << '\n'; } output = out.str (); @@ -215,7 +215,7 @@ int CmdCompletionUDAs::execute (std::string& output) { std::sort (udas.begin (), udas.end ()); join (output, "\n", udas); - output += "\n"; + output += '\n'; } return 0; diff --git a/src/commands/CmdUnique.cpp b/src/commands/CmdUnique.cpp index de364c3d0..8b28f9020 100644 --- a/src/commands/CmdUnique.cpp +++ b/src/commands/CmdUnique.cpp @@ -87,7 +87,7 @@ int CmdUnique::execute (std::string& output) // Generate list of unique values. for (auto& value : values) - output += value + "\n"; + output += value + '\n'; context.headers.clear (); return 0; diff --git a/src/commands/CmdUrgency.cpp b/src/commands/CmdUrgency.cpp index 31e6cd71a..4d45a65bf 100644 --- a/src/commands/CmdUrgency.cpp +++ b/src/commands/CmdUrgency.cpp @@ -74,7 +74,7 @@ int CmdUrgency::execute (std::string& output) out << format (STRING_CMD_URGENCY_RESULT, task.identifier (), Lexer::trim (format (task.urgency (), 6, 3))) - << "\n"; + << '\n'; } output = out.str (); diff --git a/src/commands/CmdVersion.cpp b/src/commands/CmdVersion.cpp index 30724c779..ce1432fb2 100644 --- a/src/commands/CmdVersion.cpp +++ b/src/commands/CmdVersion.cpp @@ -76,7 +76,7 @@ int CmdVersion::execute (std::string& output) if (context.color ()) bold = Color ("bold"); - out << "\n" + out << '\n' << format (STRING_CMD_VERSION_BUILT, bold.colorize (PACKAGE), bold.colorize (VERSION)) #if defined (DARWIN) @@ -104,23 +104,23 @@ int CmdVersion::execute (std::string& output) #endif #if PACKAGE_LANGUAGE != LANGUAGE_ENG_USA - << " " + << ' ' << STRING_LOCALIZATION_DESC #endif - << "\n" + << '\n' << STRING_CMD_VERSION_COPY - << "\n" - << "\n" + << '\n' + << '\n' << disclaimer.render () - << "\n" + << '\n' << link.render () - << "\n"; + << '\n'; #if PACKAGE_LANGUAGE != LANGUAGE_ENG_USA out << STRING_LOCALIZATION_AUTHOR - << "\n" - << "\n"; + << '\n' + << '\n'; #endif output = out.str (); @@ -154,7 +154,7 @@ int CmdCompletionVersion::execute (std::string& output) #else output = VERSION; #endif - output += "\n"; + output += '\n'; return 0; } diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 4783afc68..86a276f83 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -350,7 +350,7 @@ bool Command::permission ( return true; if (context.verbose ("blank") && !_first_iteration) - std::cout << "\n"; + std::cout << '\n'; int answer = confirm4 (question); _first_iteration = false; switch (answer) diff --git a/src/dependency.cpp b/src/dependency.cpp index 124610d6f..a1cc51e6a 100644 --- a/src/dependency.cpp +++ b/src/dependency.cpp @@ -67,7 +67,6 @@ void dependencyGetBlocking (const Task& task, std::vector & blocking) // Returns true if the supplied task adds a cycle to the dependency chain. bool dependencyIsCircular (const Task& task) { - // A new task has no UUID assigned yet, and therefore cannot be part of any // dependency chain. if (task.has ("uuid")) @@ -163,7 +162,7 @@ void dependencyChainOnComplete (Task& task) << "\n"; for (auto& b : blocking) - std::cout << " " << b.id << " " << b.get ("description") << "\n"; + std::cout << " " << b.id << ' ' << b.get ("description") << "\n"; } // If there are both blocking and blocked tasks, the chain is broken. @@ -175,7 +174,7 @@ void dependencyChainOnComplete (Task& task) << "\n"; for (auto& b : blocked) - std::cout << " " << b.id << " " << b.get ("description") << "\n"; + std::cout << " " << b.id << ' ' << b.get ("description") << "\n"; } if (!context.config.getBoolean ("dependency.confirmation") || @@ -218,7 +217,7 @@ void dependencyChainOnStart (Task& task) << "\n"; for (auto& b : blocking) - std::cout << " " << b.id << " " << b.get ("description") << "\n"; + std::cout << " " << b.id << ' ' << b.get ("description") << "\n"; } } } diff --git a/src/feedback.cpp b/src/feedback.cpp index 49f5a4556..c5c88b86a 100644 --- a/src/feedback.cpp +++ b/src/feedback.cpp @@ -478,7 +478,7 @@ std::string onProjectChange (Task& task, bool scope /* = true */) percentage = (count_done * 100 / (count_done + count_pending)); msg << format (STRING_HELPER_PROJECT_COMPL, project, percentage) - << " "; + << ' '; if (count_pending == 1 && count_done == 0) msg << format (STRING_HELPER_PROJECT_REM1, count_pending); From 89227288884bbd120baa074c7dff46c0209a356c Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 14 Oct 2016 23:11:28 -0400 Subject: [PATCH 0100/1455] Cleanup: Don't use string literals when character literals are needed --- src/Msg.cpp | 6 ++-- src/TDB2.cpp | 60 ++++++++++++++++----------------- src/Task.cpp | 58 +++++++++++++++---------------- src/columns/ColDepends.cpp | 2 +- src/columns/ColDescription.cpp | 4 +-- src/columns/ColProject.cpp | 6 ++-- src/columns/ColRecur.cpp | 2 +- src/columns/ColTags.cpp | 6 ++-- src/columns/ColTypeDate.cpp | 10 +++--- src/columns/ColTypeDuration.cpp | 2 +- src/columns/ColTypeNumeric.cpp | 2 +- src/columns/ColTypeString.cpp | 4 +-- src/commands/CmdAttributes.cpp | 2 +- src/commands/CmdBurndown.cpp | 4 +-- src/commands/CmdCommands.cpp | 4 +-- src/commands/CmdConfig.cpp | 14 ++++---- src/commands/CmdDiagnostics.cpp | 8 ++--- src/commands/CmdEdit.cpp | 2 +- src/commands/CmdExport.cpp | 2 +- src/commands/CmdHistory.cpp | 12 +++---- src/commands/CmdIDs.cpp | 6 ++-- src/commands/CmdInfo.cpp | 8 ++--- src/commands/CmdStats.cpp | 2 +- src/rules.cpp | 2 +- src/text.cpp | 2 +- src/text.h | 2 +- src/util.cpp | 12 +++---- 27 files changed, 122 insertions(+), 122 deletions(-) diff --git a/src/Msg.cpp b/src/Msg.cpp index 7f73858c4..bed357e11 100644 --- a/src/Msg.cpp +++ b/src/Msg.cpp @@ -72,9 +72,9 @@ std::string Msg::serialize () const { std::string output; for (auto& i : _header) - output += i.first + ": " + i.second + "\n"; + output += i.first + ": " + i.second + '\n'; - output += "\n" + _payload + "\n"; + output += '\n' + _payload + '\n'; return output; } @@ -95,7 +95,7 @@ bool Msg::parse (const std::string& input) { 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[Lexer::trim (i.substr (0, delimiter))] = Lexer::trim (i.substr (delimiter + 1)); } diff --git a/src/TDB2.cpp b/src/TDB2.cpp index 0f3e696c3..f53332aed 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -61,7 +61,7 @@ TF2::~TF2 () { if (_dirty && TDB2::debug_mode) std::cout << format (STRING_TDB2_DIRTY_EXIT, std::string (_file)) - << "\n"; + << '\n'; } //////////////////////////////////////////////////////////////////////////////// @@ -301,7 +301,7 @@ void TF2::commit () for (auto& task : _tasks) // Skip over the tasks that are marked to be purged if (_purged_tasks.find (task.get ("uuid")) == _purged_tasks.end ()) - _file.write_raw (task.composeF4 () + "\n"); + _file.write_raw (task.composeF4 () + '\n'); // Write out all the added lines. _file.append (_added_lines); @@ -708,9 +708,9 @@ void TDB2::update ( // old // new // --- - undo.add_line ("time " + ISO8601d ().toEpochString () + "\n"); - undo.add_line ("old " + original.composeF4 () + "\n"); - undo.add_line ("new " + task.composeF4 () + "\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"); } else @@ -727,14 +727,14 @@ void TDB2::update ( // time y_;6omd*Y^y>Jvjv_+;#j~_H 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ξ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

ahuGbh&C0VhroAevCY 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

s-BpXrS;^24ve4 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�{cPRWhF9Z8CEy!{~64sqj>VEXQ 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

b=%&Ixl4k+gAYL6O!&Rq>nnZ=8>CGLPWnfYH-1j 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

4t8*#fSGO2le8vaa_G?@^(g?|&^tbWRKG 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 b|4EfVjgtD`NszB3ZaoXwrNoK^K>L3H&Y^EF diff --git a/doc/ref/task-ref.pdf b/doc/ref/task-ref.pdf index 0b72893562ddfac6ee729c957209a1b9438c47d0..349f3c4a6e476dc0bc298920c6de05720c1289fc 100644 GIT binary patch delta 79289 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

au6vm?rO*ue(OxeQTYs{B$v4e+xS}0lWlI z!a%2hXRHX58M6b7bsR%_HH0v8q=F}Tko0MUYqCk;BHe*zi!cI_KeNcDR8*kv`#uZU z+f#t8am>=&%H}if+qo%s{q4&wk%-*0*VmP+hg}MOg{VHnb*}P_%C}0_Lf-;eM&Tp7&p|C%aXm~yJ?9pOm|mWa(9o}bU-l;~^j zsKPGVc3ilQmumU8?Fbt>0}ujOVe4lA1*DmP85qwwfC{SMNp`=uGdWY|w7NgT~VMxNYEN8)HGJ>DRWnI!O$u(u| zTz#sH)N33I`t)XkNoMA$7gb5V=)-NKZdBJG&MSm532ey&sRippB19~ssuy$hR;w5m z3j?>_RguvB&8@jwy&K18)#)0+!Uuvez^k+sD68^UB!}e<` z)a*)5_NJ~TW=_<9DFp|_;N5Vsho}GETkY@k8+$u(BNsDj$U|drA$fb#hcw22(n3Q2 z)zZVs%p8M*8p4ag@y|sK;o<^wQJYi$g#kglAb4AF&EOZc-QOSwkORmG*Y95#go6VD zf%RSjo+E-dV8@pLS|}U>!(ZY4mlzPj0fy`PFN~8H#LN2|#tY=(g&Y1~a$MY?hdt!} zg+YMaV0btGg>mwNLGX4J{snTu4Gn)D{a*~o0pSMyRv{3`#mW0yg+LG|h=&WddhfLt8Ey95G+@ca=yAkK%e`|n0T+<#aLJ|4J# zSCAJz9R6|>y#N1b%?siI{pP!eIOq5ub3HT$$9TDaQwGSv4Fdg+!N&vlZwkW42;9g2 zqx6IQ;UF*fZ#{k(IKP_}j=@LA{}g^G3*zMA`UB(T;Qh_i@Yx6m{LKmv*bC0zHH1%F zaGN}I^dHMSOl2TW82ded%pAf?&8}i^??U}B7d=do(st(d)bK$0>$fDhW;|RFpb0mJk*O)C5m*T0|0@D3y$3wSfR8y0diqz25*YsnM>pUN delta 74891 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 Date: Sun, 27 Nov 2016 13:36:53 -0500 Subject: [PATCH 0138/1455] libshared: Updated to 9473050234dd3a90bff5400a081ee54881b6b0f5 --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index ce5c3414d..947305023 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit ce5c3414de56a2d1390893bbdc46e7116c38cd90 +Subproject commit 9473050234dd3a90bff5400a081ee54881b6b0f5 From 456925a02b72ed50fa935c08f2c6287df8e5e4b1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 5 Dec 2016 23:34:52 -0500 Subject: [PATCH 0139/1455] libshared: Updated to 2af7d037559f84450fffa812829fc553498a7ae4 --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index 947305023..2af7d0375 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit 9473050234dd3a90bff5400a081ee54881b6b0f5 +Subproject commit 2af7d037559f84450fffa812829fc553498a7ae4 From 355620c6403d56baa809e51abb347b5c7394693e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 6 Dec 2016 07:20:45 -0500 Subject: [PATCH 0140/1455] libhsared: migrating from local to libshared --- src/CLI2.cpp | 10 +- src/CMakeLists.txt | 6 +- src/Color.cpp | 6 +- src/Config.cpp | 1 + src/Context.cpp | 10 +- src/DOM.cpp | 6 +- src/Dates.cpp | 2 +- src/Eval.cpp | 3 +- src/Filter.cpp | 4 +- src/Hooks.cpp | 10 +- src/ISO8601.cpp | 3 +- src/TDB2.cpp | 4 +- src/TLSClient.cpp | 2 +- src/Task.cpp | 67 ++++----- src/Variant.cpp | 2 +- src/ViewTask.cpp | 1 + src/ViewText.cpp | 1 + src/columns/ColDepends.cpp | 15 +- src/columns/ColDescription.cpp | 3 +- src/columns/ColID.cpp | 2 +- src/columns/ColIMask.cpp | 2 +- src/columns/ColMask.cpp | 2 +- src/columns/ColParent.cpp | 2 +- src/columns/ColProject.cpp | 3 +- src/columns/ColRecur.cpp | 3 +- src/columns/ColStatus.cpp | 2 +- src/columns/ColString.cpp | 2 + src/columns/ColTags.cpp | 19 +-- src/columns/ColTypeDate.cpp | 2 +- src/columns/ColTypeDuration.cpp | 2 +- src/columns/ColTypeNumeric.cpp | 2 +- src/columns/ColTypeString.cpp | 2 +- src/columns/ColUDA.cpp | 3 +- src/columns/ColUUID.cpp | 2 +- src/columns/ColUrgency.cpp | 2 +- src/columns/Column.cpp | 11 +- src/commands/CmdAdd.cpp | 4 +- src/commands/CmdAnnotate.cpp | 4 +- src/commands/CmdAppend.cpp | 4 +- src/commands/CmdCalendar.cpp | 3 +- src/commands/CmdColor.cpp | 3 +- src/commands/CmdColumns.cpp | 1 + src/commands/CmdConfig.cpp | 4 +- src/commands/CmdContext.cpp | 3 +- src/commands/CmdCount.cpp | 2 +- src/commands/CmdCustom.cpp | 1 + src/commands/CmdDelete.cpp | 2 +- src/commands/CmdDenotate.cpp | 3 +- src/commands/CmdDiagnostics.cpp | 2 +- src/commands/CmdDone.cpp | 2 +- src/commands/CmdDuplicate.cpp | 2 +- src/commands/CmdEdit.cpp | 12 +- src/commands/CmdGet.cpp | 5 +- src/commands/CmdHelp.cpp | 3 +- src/commands/CmdHistory.cpp | 1 + src/commands/CmdIDs.cpp | 11 +- src/commands/CmdImport.cpp | 1 + src/commands/CmdInfo.cpp | 2 + src/commands/CmdLog.cpp | 2 +- src/commands/CmdModify.cpp | 2 +- src/commands/CmdPrepend.cpp | 2 +- src/commands/CmdProjects.cpp | 1 + src/commands/CmdPurge.cpp | 2 +- src/commands/CmdReports.cpp | 1 + src/commands/CmdShow.cpp | 2 +- src/commands/CmdStart.cpp | 2 +- src/commands/CmdStats.cpp | 1 + src/commands/CmdStop.cpp | 2 +- src/commands/CmdSummary.cpp | 1 + src/commands/CmdSync.cpp | 9 +- src/commands/CmdTags.cpp | 1 + src/commands/CmdTimesheet.cpp | 2 +- src/commands/CmdUDAs.cpp | 1 + src/commands/CmdUnique.cpp | 2 +- src/commands/CmdUrgency.cpp | 2 +- src/commands/CmdVersion.cpp | 2 +- src/commands/Command.cpp | 3 +- src/dependency.cpp | 2 +- src/feedback.cpp | 9 +- src/legacy.cpp | 2 +- src/main.h | 16 --- src/recur.cpp | 2 +- src/rules.cpp | 2 +- src/sort.cpp | 6 +- src/text.cpp | 242 -------------------------------- src/text.h | 42 ------ src/util.cpp | 37 +---- src/util.h | 1 - 88 files changed, 185 insertions(+), 510 deletions(-) diff --git a/src/CLI2.cpp b/src/CLI2.cpp index c8a2d06db..55dfc1aa5 100644 --- a/src/CLI2.cpp +++ b/src/CLI2.cpp @@ -32,8 +32,8 @@ #include #include #include -#include -#include +#include +#include #include extern Context context; @@ -1480,8 +1480,7 @@ void CLI2::findIDs () else if (a._lextype == Lexer::Type::set) { // Split the ID list into elements. - std::vector elements; - split (elements, a.attribute ("raw"), ','); + auto elements = split (a.attribute ("raw"), ','); for (auto& element : elements) { @@ -1536,8 +1535,7 @@ void CLI2::findIDs () a.tag ("FILTER"); // Split the ID list into elements. - std::vector elements; - split (elements, raw, ','); + auto elements = split (raw, ','); for (const auto& element : elements) { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6eaee7cf0..3d4e5f9d3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,12 +35,16 @@ add_library (task CLI2.cpp CLI2.h text.cpp text.h util.cpp util.h) -add_library (libshared libshared/src/FS.cpp libshared/src/FS.h +add_library (libshared libshared/src/Datetime.cpp libshared/src/Datetime.h + libshared/src/Duration.cpp libshared/src/Duration.h + libshared/src/FS.cpp libshared/src/FS.h libshared/src/JSON.cpp libshared/src/JSON.h libshared/src/Pig.cpp libshared/src/Pig.h libshared/src/RX.cpp libshared/src/RX.h libshared/src/Table.cpp libshared/src/Table.h libshared/src/Timer.cpp libshared/src/Timer.h + libshared/src/shared.cpp libshared/src/shared.h + libshared/src/format.cpp libshared/src/format.h libshared/src/unicode.cpp libshared/src/unicode.h libshared/src/utf8.cpp libshared/src/utf8.h libshared/src/wcwidth6.cpp) diff --git a/src/Color.cpp b/src/Color.cpp index 557fdfea6..a516e2270 100644 --- a/src/Color.cpp +++ b/src/Color.cpp @@ -31,7 +31,8 @@ #include #include #include -#include +#include +#include #include #include @@ -130,8 +131,7 @@ Color::Color (const std::string& spec) : _value (0) { // Split spec into words. - std::vector words; - split (words, spec, ' '); + auto words = split (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 diff --git a/src/Config.cpp b/src/Config.cpp index be606f8bb..681a101ce 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include diff --git a/src/Context.cpp b/src/Context.cpp index 518099b13..61c591531 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -39,8 +39,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -576,7 +576,8 @@ bool Context::verbose (const std::string& token) if (verbosity.empty ()) { verbosity_legacy = config.getBoolean ("verbose"); - split (verbosity, config.get ("verbose"), ','); + for (auto& token : split (config.get ("verbose"), ',')) + verbosity.insert (token); // Regular feedback means almost everything. // This odd test is to see if a Boolean-false value is a real one, which @@ -700,8 +701,7 @@ void Context::staticInitialization () rc.first.substr (rc.first.length () - 7, 7) == ".values") { std::string name = rc.first.substr (4, rc.first.length () - 7 - 4); - std::vector values; - split (values, rc.second, ','); + auto values = split (rc.second, ','); for (auto r = values.rbegin(); r != values.rend (); ++r) Task::customOrder[name].push_back (*r); diff --git a/src/DOM.cpp b/src/DOM.cpp index f1b06bbd9..88b6c3c65 100644 --- a/src/DOM.cpp +++ b/src/DOM.cpp @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include #include @@ -189,8 +190,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) } // split name on '.' - std::vector elements; - split (elements, name, '.'); + auto elements = split (name, '.'); Task ref (task); Nibbler n (elements[0]); diff --git a/src/Dates.cpp b/src/Dates.cpp index a721b6a49..1cb4273f0 100644 --- a/src/Dates.cpp +++ b/src/Dates.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/Eval.cpp b/src/Eval.cpp index 9736d0981..f4f0a2a2f 100644 --- a/src/Eval.cpp +++ b/src/Eval.cpp @@ -31,7 +31,8 @@ #include #include #include -#include +#include +#include #include extern Context context; diff --git a/src/Filter.cpp b/src/Filter.cpp index 169ae9ac2..9e7d06c07 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -34,8 +34,8 @@ #include #include #include -#include -#include +#include +#include extern Context context; diff --git a/src/Hooks.cpp b/src/Hooks.cpp index abff63366..109aa0490 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -39,10 +39,12 @@ #include #include #include +#include #include #include +#include +#include #include -#include #include extern Context context; @@ -468,7 +470,9 @@ void Hooks::assertSameTask (const std::vector & input, const Task& } json::string* up = (json::string*) u->second; - std::string json_uuid = json::decode (unquoteText (up->dump ())); + auto text = up->dump (); + Lexer::dequote (text); + std::string json_uuid = json::decode (text); if (json_uuid != uuid) { context.error (format (STRING_HOOK_ERROR_SAME2, uuid, json_uuid)); @@ -562,7 +566,7 @@ int Hooks::callHookScript ( else status = execute (script, args, inputStr, outputStr); - split (output, outputStr, '\n'); + output = split (outputStr, '\n'); if (_debug >= 2) { diff --git a/src/ISO8601.cpp b/src/ISO8601.cpp index 0830c21fd..9528393dc 100644 --- a/src/ISO8601.cpp +++ b/src/ISO8601.cpp @@ -35,7 +35,8 @@ #ifdef PRODUCT_TASKWARRIOR #include #endif -#include +#include +#include #include #include diff --git a/src/TDB2.cpp b/src/TDB2.cpp index fa5cea3da..b8caae2b0 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -37,8 +37,8 @@ #include #include #include -#include -#include +#include +#include #include extern Context context; diff --git a/src/TLSClient.cpp b/src/TLSClient.cpp index 8f7653db8..1a9927daf 100644 --- a/src/TLSClient.cpp +++ b/src/TLSClient.cpp @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #define MAX_BUF 16384 diff --git a/src/Task.cpp b/src/Task.cpp index 1b2d3d8f7..a284b849e 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -45,7 +45,8 @@ #ifdef PRODUCT_TASKWARRIOR #include #endif -#include +#include +#include #include #include @@ -712,8 +713,7 @@ void Task::parseJSON (const json::object* root_obj) else if (i.first == "depends" && i.second->type() == json::j_string) { json::string* deps = (json::string*)i.second; - std::vector uuids; - split (uuids, deps->_data, ','); + auto uuids = split (deps->_data, ','); for (const auto& uuid : uuids) addDependency (uuid); @@ -721,11 +721,19 @@ void Task::parseJSON (const json::object* root_obj) // Strings are decoded. else if (type == "string") - set (i.first, json::decode (unquoteText (i.second->dump ()))); + { + auto text = i.second->dump (); + Lexer::dequote (text); + set (i.first, json::decode (text)); + } // Other types are simply added. else - set (i.first, unquoteText (i.second->dump ())); + { + auto text = i.second->dump (); + Lexer::dequote (text); + set (i.first, text); + } } // UDA orphans and annotations do not have columns. @@ -769,7 +777,9 @@ void Task::parseJSON (const json::object* root_obj) << "' --> preserved\n"; context.debug (message.str ()); #endif - set (i.first, json::decode (unquoteText (i.second->dump ()))); + auto text = i.second->dump (); + Lexer::dequote (text); + set (i.first, json::decode (text)); } } } @@ -909,8 +919,7 @@ std::string Task::composeJSON (bool decorate /*= false*/) const // Tags are converted to an array. else if (i.first == "tags") { - std::vector tags; - split (tags, i.second, ','); + auto tags = split (i.second, ','); out << "\"tags\":["; @@ -949,8 +958,7 @@ std::string Task::composeJSON (bool decorate /*= false*/) const #endif ) { - std::vector deps; - split (deps, i.second, ','); + auto deps = split (i.second, ','); out << "\"depends\":["; @@ -1148,16 +1156,13 @@ void Task::addDependency (const std::string& uuid) //////////////////////////////////////////////////////////////////////////////// void Task::removeDependency (const std::string& uuid) { - std::vector deps; - split (deps, get ("depends"), ','); + auto deps = split (get ("depends"), ','); auto i = std::find (deps.begin (), deps.end (), uuid); if (i != deps.end ()) { deps.erase (i); - std::string combined; - join (combined, ",", deps); - set ("depends", combined); + set ("depends", join (",", deps)); recalc_urgency = true; } else @@ -1178,8 +1183,7 @@ void Task::removeDependency (int id) //////////////////////////////////////////////////////////////////////////////// void Task::getDependencies (std::vector & all) const { - std::vector deps; - split (deps, get ("depends"), ','); + auto deps = split (get ("depends"), ','); all.clear (); @@ -1190,15 +1194,13 @@ void Task::getDependencies (std::vector & all) const //////////////////////////////////////////////////////////////////////////////// void Task::getDependencies (std::vector & all) const { - all.clear (); - split (all, get ("depends"), ','); + all = split (get ("depends"), ','); } //////////////////////////////////////////////////////////////////////////////// void Task::getDependencies (std::vector & all) const { - std::vector deps; - split (deps, get ("depends"), ','); + std::vector deps = split (get ("depends"), ','); all.clear (); @@ -1214,9 +1216,7 @@ void Task::getDependencies (std::vector & all) const //////////////////////////////////////////////////////////////////////////////// int Task::getTagCount () const { - std::vector tags; - split (tags, get ("tags"), ','); - + auto tags = split (get ("tags"), ','); return (int) tags.size (); } @@ -1275,8 +1275,7 @@ bool Task::hasTag (const std::string& tag) const } // Concrete tags. - std::vector tags; - split (tags, get ("tags"), ','); + auto tags = split (get ("tags"), ','); if (std::find (tags.begin (), tags.end (), tag) != tags.end ()) return true; @@ -1287,15 +1286,12 @@ bool Task::hasTag (const std::string& tag) const //////////////////////////////////////////////////////////////////////////////// void Task::addTag (const std::string& tag) { - std::vector tags; - split (tags, get ("tags"), ','); + auto tags = split (get ("tags"), ','); if (std::find (tags.begin (), tags.end (), tag) == tags.end ()) { tags.push_back (tag); - std::string combined; - join (combined, ",", tags); - set ("tags", combined); + set ("tags", join (",", tags)); recalc_urgency = true; } @@ -1315,22 +1311,19 @@ void Task::addTags (const std::vector & tags) //////////////////////////////////////////////////////////////////////////////// void Task::getTags (std::vector& tags) const { - split (tags, get ("tags"), ','); + tags = split (get ("tags"), ','); } //////////////////////////////////////////////////////////////////////////////// void Task::removeTag (const std::string& tag) { - std::vector tags; - split (tags, get ("tags"), ','); + auto tags = split (get ("tags"), ','); auto i = std::find (tags.begin (), tags.end (), tag); if (i != tags.end ()) { tags.erase (i); - std::string combined; - join (combined, ",", tags); - set ("tags", combined); + set ("tags", join (",", tags)); } recalc_urgency = true; diff --git a/src/Variant.cpp b/src/Variant.cpp index 1de474e85..a4a287515 100644 --- a/src/Variant.cpp +++ b/src/Variant.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include std::string Variant::dateFormat = ""; diff --git a/src/ViewTask.cpp b/src/ViewTask.cpp index b0562995f..4c2f9bff1 100644 --- a/src/ViewTask.cpp +++ b/src/ViewTask.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/src/ViewText.cpp b/src/ViewText.cpp index 07502e9ea..c1d8455d8 100644 --- a/src/ViewText.cpp +++ b/src/ViewText.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/src/columns/ColDepends.cpp b/src/columns/ColDepends.cpp index 0d2d27142..ce425776b 100644 --- a/src/columns/ColDepends.cpp +++ b/src/columns/ColDepends.cpp @@ -28,7 +28,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -91,8 +92,7 @@ void ColumnDepends::measure (Task& task, unsigned int& minimum, unsigned int& ma for (auto& i : blocking) blocking_ids.push_back (i.id); - std::string all; - join (all, " ", blocking_ids); + auto all = join (" ", blocking_ids); maximum = all.length (); unsigned int length; @@ -134,8 +134,7 @@ void ColumnDepends::render ( for (const auto& t : blocking) blocking_ids.push_back (t.id); - std::string combined; - join (combined, " ", blocking_ids); + auto combined = join (" ", blocking_ids); std::vector all; wrapText (all, combined, width, _hyphenate); @@ -150,12 +149,8 @@ void ColumnDepends::render ( //////////////////////////////////////////////////////////////////////////////// void ColumnDepends::modify (Task& task, const std::string& value) { - // Parse IDs - std::vector deps; - split (deps, value, ','); - // Apply or remove dendencies in turn. - for (auto& dep : deps) + for (auto& dep : split (value, ',')) { if (dep[0] == '-') { diff --git a/src/columns/ColDescription.cpp b/src/columns/ColDescription.cpp index ac84b694c..f45358858 100644 --- a/src/columns/ColDescription.cpp +++ b/src/columns/ColDescription.cpp @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/src/columns/ColID.cpp b/src/columns/ColID.cpp index de2f41fa3..48e7c016c 100644 --- a/src/columns/ColID.cpp +++ b/src/columns/ColID.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColIMask.cpp b/src/columns/ColIMask.cpp index 97ef05143..5f053fa98 100644 --- a/src/columns/ColIMask.cpp +++ b/src/columns/ColIMask.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColMask.cpp b/src/columns/ColMask.cpp index a00d7b8a8..08a8e70e5 100644 --- a/src/columns/ColMask.cpp +++ b/src/columns/ColMask.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColParent.cpp b/src/columns/ColParent.cpp index 3d1622c0b..38518681f 100644 --- a/src/columns/ColParent.cpp +++ b/src/columns/ColParent.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColProject.cpp b/src/columns/ColProject.cpp index e13162469..069563db8 100644 --- a/src/columns/ColProject.cpp +++ b/src/columns/ColProject.cpp @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/src/columns/ColRecur.cpp b/src/columns/ColRecur.cpp index cd8cc8327..aa1c85397 100644 --- a/src/columns/ColRecur.cpp +++ b/src/columns/ColRecur.cpp @@ -33,7 +33,8 @@ #include #include #include -#include +#include +#include #include #include diff --git a/src/columns/ColStatus.cpp b/src/columns/ColStatus.cpp index ebc0b222e..ef403bd00 100644 --- a/src/columns/ColStatus.cpp +++ b/src/columns/ColStatus.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include diff --git a/src/columns/ColString.cpp b/src/columns/ColString.cpp index 581ce491a..5befb51e5 100644 --- a/src/columns/ColString.cpp +++ b/src/columns/ColString.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include diff --git a/src/columns/ColTags.cpp b/src/columns/ColTags.cpp index 6b28b4c4b..c32232030 100644 --- a/src/columns/ColTags.cpp +++ b/src/columns/ColTags.cpp @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -96,8 +97,7 @@ void ColumnTags::measure (Task& task, unsigned int& minimum, unsigned int& maxim // Find the widest tag. if (tags.find (',') != std::string::npos) { - std::vector all; - split (all, tags, ','); + auto all = split (tags, ','); for (const auto& tag : all) { auto length = utf8_width (tag); @@ -132,10 +132,9 @@ void ColumnTags::render ( { if (tags.find (',') != std::string::npos) { - std::vector all; - split (all, tags, ','); + auto all = split (tags, ','); std::sort (all.begin (), all.end ()); - join (tags, " ", all); + tags = join (" ", all); all.clear (); wrapText (all, tags, width, _hyphenate); @@ -152,8 +151,7 @@ void ColumnTags::render ( } else if (_style == "count") { - std::vector all; - split (all, tags, ','); + auto all = split (tags, ','); renderStringRight (lines, width, color, '[' + format (static_cast (all.size ())) + ']'); } } @@ -167,10 +165,7 @@ void ColumnTags::modify (Task& task, const std::string& value) // TW-1701 task.set ("tags", ""); - std::vector tags; - split (tags, value, ','); - - for (auto& tag : tags) + for (auto& tag : split (value, ',')) { // If it's a DOM ref, eval it first. Lexer lexer (tag); diff --git a/src/columns/ColTypeDate.cpp b/src/columns/ColTypeDate.cpp index 727402d32..c996f3f4f 100644 --- a/src/columns/ColTypeDate.cpp +++ b/src/columns/ColTypeDate.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/columns/ColTypeDuration.cpp b/src/columns/ColTypeDuration.cpp index 344fd130a..b3e433d81 100644 --- a/src/columns/ColTypeDuration.cpp +++ b/src/columns/ColTypeDuration.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/columns/ColTypeNumeric.cpp b/src/columns/ColTypeNumeric.cpp index 40925c042..b69147f1f 100644 --- a/src/columns/ColTypeNumeric.cpp +++ b/src/columns/ColTypeNumeric.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/columns/ColTypeString.cpp b/src/columns/ColTypeString.cpp index 3e18f087c..af91ae008 100644 --- a/src/columns/ColTypeString.cpp +++ b/src/columns/ColTypeString.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/columns/ColUDA.cpp b/src/columns/ColUDA.cpp index 9a4016219..d2f316a3c 100644 --- a/src/columns/ColUDA.cpp +++ b/src/columns/ColUDA.cpp @@ -28,7 +28,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/src/columns/ColUUID.cpp b/src/columns/ColUUID.cpp index 48baf9769..83f1a7dc9 100644 --- a/src/columns/ColUUID.cpp +++ b/src/columns/ColUUID.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColUrgency.cpp b/src/columns/ColUrgency.cpp index b2bf3911f..82a6586ca 100644 --- a/src/columns/ColUrgency.cpp +++ b/src/columns/ColUrgency.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/Column.cpp b/src/columns/Column.cpp index c3b1b8e4c..75e4e6bd5 100644 --- a/src/columns/Column.cpp +++ b/src/columns/Column.cpp @@ -51,7 +51,8 @@ #include #include #include -#include +#include +#include #include extern Context context; @@ -186,7 +187,7 @@ Column* Column::uda (const std::string& name) c->_name = name; c->_label = label; if (values != "") - split (c->_values, values, ','); + c->_values = split (values, ','); return c; } else if (type == "numeric") @@ -195,7 +196,7 @@ Column* Column::uda (const std::string& name) c->_name = name; c->_label = label; if (values != "") - split (c->_values, values, ','); + c->_values = split (values, ','); return c; } else if (type == "date") @@ -204,7 +205,7 @@ Column* Column::uda (const std::string& name) c->_name = name; c->_label = label; if (values != "") - split (c->_values, values, ','); + c->_values = split (values, ','); return c; } else if (type == "duration") @@ -213,7 +214,7 @@ Column* Column::uda (const std::string& name) c->_name = name; c->_label = label; if (values != "") - split (c->_values, values, ','); + c->_values = split (values, ','); return c; } else if (type != "") diff --git a/src/commands/CmdAdd.cpp b/src/commands/CmdAdd.cpp index efca8d798..e9dd03792 100644 --- a/src/commands/CmdAdd.cpp +++ b/src/commands/CmdAdd.cpp @@ -27,9 +27,9 @@ #include #include #include -#include +#include +#include #include -#include #include extern Context context; diff --git a/src/commands/CmdAnnotate.cpp b/src/commands/CmdAnnotate.cpp index 932ee027b..e980b75e6 100644 --- a/src/commands/CmdAnnotate.cpp +++ b/src/commands/CmdAnnotate.cpp @@ -30,8 +30,8 @@ #include #include #include -#include -#include +#include +#include #include extern Context context; diff --git a/src/commands/CmdAppend.cpp b/src/commands/CmdAppend.cpp index 5be95aee9..e3fe1a3ec 100644 --- a/src/commands/CmdAppend.cpp +++ b/src/commands/CmdAppend.cpp @@ -29,8 +29,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/src/commands/CmdCalendar.cpp b/src/commands/CmdCalendar.cpp index f71e6e8c2..6bc259051 100644 --- a/src/commands/CmdCalendar.cpp +++ b/src/commands/CmdCalendar.cpp @@ -33,8 +33,9 @@ #include #include #include +#include +#include #include -#include #include #include diff --git a/src/commands/CmdColor.cpp b/src/commands/CmdColor.cpp index 7262c614c..231bf3ab7 100644 --- a/src/commands/CmdColor.cpp +++ b/src/commands/CmdColor.cpp @@ -31,7 +31,8 @@ #include #include #include -#include +#include +#include #include extern Context context; diff --git a/src/commands/CmdColumns.cpp b/src/commands/CmdColumns.cpp index 3696bb802..8772a9e85 100644 --- a/src/commands/CmdColumns.cpp +++ b/src/commands/CmdColumns.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/src/commands/CmdConfig.cpp b/src/commands/CmdConfig.cpp index f3d808286..bf938e8a9 100644 --- a/src/commands/CmdConfig.cpp +++ b/src/commands/CmdConfig.cpp @@ -31,8 +31,8 @@ #include #include #include -#include -#include +#include +#include extern Context context; diff --git a/src/commands/CmdContext.cpp b/src/commands/CmdContext.cpp index 0767c5e3a..057b8d6f8 100644 --- a/src/commands/CmdContext.cpp +++ b/src/commands/CmdContext.cpp @@ -33,7 +33,8 @@ #include #include #include -#include +#include +#include #include extern Context context; diff --git a/src/commands/CmdCount.cpp b/src/commands/CmdCount.cpp index a9e5d2043..4f97506d8 100644 --- a/src/commands/CmdCount.cpp +++ b/src/commands/CmdCount.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include //////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index 1c78dd2ca..cc45fff3d 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include diff --git a/src/commands/CmdDelete.cpp b/src/commands/CmdDelete.cpp index 1697483b8..0bfc1c8ae 100644 --- a/src/commands/CmdDelete.cpp +++ b/src/commands/CmdDelete.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/commands/CmdDenotate.cpp b/src/commands/CmdDenotate.cpp index 1f958f8fa..7bd040aa5 100644 --- a/src/commands/CmdDenotate.cpp +++ b/src/commands/CmdDenotate.cpp @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/src/commands/CmdDiagnostics.cpp b/src/commands/CmdDiagnostics.cpp index 9e0a50fd3..15362bf99 100644 --- a/src/commands/CmdDiagnostics.cpp +++ b/src/commands/CmdDiagnostics.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #ifdef HAVE_COMMIT #include diff --git a/src/commands/CmdDone.cpp b/src/commands/CmdDone.cpp index 253ffb4b4..5ddcfa2f1 100644 --- a/src/commands/CmdDone.cpp +++ b/src/commands/CmdDone.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/commands/CmdDuplicate.cpp b/src/commands/CmdDuplicate.cpp index 350dacabc..ab2189313 100644 --- a/src/commands/CmdDuplicate.cpp +++ b/src/commands/CmdDuplicate.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/commands/CmdEdit.cpp b/src/commands/CmdEdit.cpp index 44c6f6042..a43e99bde 100644 --- a/src/commands/CmdEdit.cpp +++ b/src/commands/CmdEdit.cpp @@ -39,7 +39,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -230,8 +231,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) std::vector tags; task.getTags (tags); - std::string allTags; - join (allTags, " ", tags); + auto allTags = join (" ", tags); if (verbose) before << "# " << STRING_EDIT_TAG_SEP << '\n'; @@ -360,8 +360,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string // tags value = findValue (after, "\n Tags:"); - std::vector tags; - split (tags, value, ' '); + auto tags = split (value, ' '); task.remove ("tags"); task.addTags (tags); @@ -676,8 +675,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string // Dependencies value = findValue (after, "\n Dependencies:"); - std::vector dependencies; - split (dependencies, value, ","); + auto dependencies = split (value, ','); task.remove ("depends"); for (auto& dep : dependencies) diff --git a/src/commands/CmdGet.cpp b/src/commands/CmdGet.cpp index 363574a66..06a911d41 100644 --- a/src/commands/CmdGet.cpp +++ b/src/commands/CmdGet.cpp @@ -30,7 +30,8 @@ #include #include #include -#include +#include +#include #include extern Context context; @@ -90,7 +91,7 @@ int CmdGet::execute (std::string& output) if (results.size () == 0) throw std::string (STRING_CMD_GET_NO_DOM); - join (output, " ", results); + output = join (" ", results); output += '\n'; return 0; } diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index de0d9af85..e04641b78 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -30,7 +30,8 @@ #include #include #include -#include +#include +#include #include extern Context context; diff --git a/src/commands/CmdHistory.cpp b/src/commands/CmdHistory.cpp index 5b5569deb..2d7e5b4c7 100644 --- a/src/commands/CmdHistory.cpp +++ b/src/commands/CmdHistory.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/src/commands/CmdIDs.cpp b/src/commands/CmdIDs.cpp index b8894d204..1b4330aeb 100644 --- a/src/commands/CmdIDs.cpp +++ b/src/commands/CmdIDs.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include extern Context context; @@ -163,8 +163,7 @@ int CmdCompletionIds::execute (std::string& output) ids.push_back (task.id); std::sort (ids.begin (), ids.end ()); - join (output, "\n", ids); - output += '\n'; + output = join ("\n", ids) + '\n'; context.headers.clear (); return 0; @@ -240,8 +239,7 @@ int CmdUUIDs::execute (std::string& output) uuids.push_back (task.get ("uuid")); std::sort (uuids.begin (), uuids.end ()); - join (output, " ", uuids); - output += '\n'; + output = join (" ", uuids) + '\n'; context.headers.clear (); return 0; @@ -277,8 +275,7 @@ int CmdCompletionUuids::execute (std::string& output) uuids.push_back (task.get ("uuid")); std::sort (uuids.begin (), uuids.end ()); - join (output, "\n", uuids); - output += '\n'; + output = join ("\n", uuids) + '\n'; context.headers.clear (); return 0; diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index ae893ac51..4ede977c0 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index 0d8ded1e7..0f6273fb1 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include diff --git a/src/commands/CmdLog.cpp b/src/commands/CmdLog.cpp index 886507578..fbbc33b67 100644 --- a/src/commands/CmdLog.cpp +++ b/src/commands/CmdLog.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/commands/CmdModify.cpp b/src/commands/CmdModify.cpp index db203e180..352939479 100644 --- a/src/commands/CmdModify.cpp +++ b/src/commands/CmdModify.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/commands/CmdPrepend.cpp b/src/commands/CmdPrepend.cpp index c0ead57f1..87162c33b 100644 --- a/src/commands/CmdPrepend.cpp +++ b/src/commands/CmdPrepend.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/commands/CmdProjects.cpp b/src/commands/CmdProjects.cpp index b1ecb8a25..8d7defea4 100644 --- a/src/commands/CmdProjects.cpp +++ b/src/commands/CmdProjects.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index ab6d3b4b7..146754617 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdReports.cpp b/src/commands/CmdReports.cpp index 4474f96bd..0fa52cb0c 100644 --- a/src/commands/CmdReports.cpp +++ b/src/commands/CmdReports.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include diff --git a/src/commands/CmdShow.cpp b/src/commands/CmdShow.cpp index 56d848ac5..296c0be66 100644 --- a/src/commands/CmdShow.cpp +++ b/src/commands/CmdShow.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/commands/CmdStart.cpp b/src/commands/CmdStart.cpp index 34f2df484..8da0c3897 100644 --- a/src/commands/CmdStart.cpp +++ b/src/commands/CmdStart.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/commands/CmdStats.cpp b/src/commands/CmdStats.cpp index 67d0a8c26..0ef70197c 100644 --- a/src/commands/CmdStats.cpp +++ b/src/commands/CmdStats.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/src/commands/CmdStop.cpp b/src/commands/CmdStop.cpp index 40dc5e33a..86d23366e 100644 --- a/src/commands/CmdStop.cpp +++ b/src/commands/CmdStop.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index 99783e2c5..1e45e6189 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/src/commands/CmdSync.cpp b/src/commands/CmdSync.cpp index 52d425761..28da9c5a8 100644 --- a/src/commands/CmdSync.cpp +++ b/src/commands/CmdSync.cpp @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include #include @@ -91,8 +92,7 @@ int CmdSync::execute (std::string& output) if (credentials_string == "") throw std::string (STRING_CMD_SYNC_BAD_CRED); - std::vector credentials; - split (credentials, credentials_string, "/"); + auto credentials = split (credentials_string, '/'); if (credentials.size () != 3) throw std::string (STRING_CMD_SYNC_BAD_CRED); @@ -198,8 +198,7 @@ int CmdSync::execute (std::string& output) int download_count = 0; payload = response.getPayload (); - std::vector lines; - split (lines, payload, '\n'); + auto lines = split (payload, '\n'); // Load all tasks, but only if necessary. There is always a sync key in // the payload, so if there are two or more lines, then we have merging diff --git a/src/commands/CmdTags.cpp b/src/commands/CmdTags.cpp index 95eedbb9a..5f75b85b3 100644 --- a/src/commands/CmdTags.cpp +++ b/src/commands/CmdTags.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/src/commands/CmdTimesheet.cpp b/src/commands/CmdTimesheet.cpp index 15d25ba55..65c1f6055 100644 --- a/src/commands/CmdTimesheet.cpp +++ b/src/commands/CmdTimesheet.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include extern Context context; diff --git a/src/commands/CmdUDAs.cpp b/src/commands/CmdUDAs.cpp index d2c20d8eb..00091d904 100644 --- a/src/commands/CmdUDAs.cpp +++ b/src/commands/CmdUDAs.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/src/commands/CmdUnique.cpp b/src/commands/CmdUnique.cpp index 8b28f9020..dbb3cadc2 100644 --- a/src/commands/CmdUnique.cpp +++ b/src/commands/CmdUnique.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdUrgency.cpp b/src/commands/CmdUrgency.cpp index 4d45a65bf..caa3587a6 100644 --- a/src/commands/CmdUrgency.cpp +++ b/src/commands/CmdUrgency.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdVersion.cpp b/src/commands/CmdVersion.cpp index ce1432fb2..b8ec3c52d 100644 --- a/src/commands/CmdVersion.cpp +++ b/src/commands/CmdVersion.cpp @@ -33,7 +33,7 @@ #ifdef HAVE_COMMIT #include #endif -#include +#include #include extern Context context; diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 86a276f83..b726e6eb8 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -28,7 +28,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/src/dependency.cpp b/src/dependency.cpp index 2f7a38db2..b8e912579 100644 --- a/src/dependency.cpp +++ b/src/dependency.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/feedback.cpp b/src/feedback.cpp index c5c88b86a..3a96f473d 100644 --- a/src/feedback.cpp +++ b/src/feedback.cpp @@ -36,8 +36,8 @@ #include #include #include -#include -#include +#include +#include #include extern Context context; @@ -52,10 +52,7 @@ std::string taskIdentifiers (const std::vector & tasks) for (auto task: tasks) identifiers.push_back (task.identifier (true)); - std::string result; - join (result, ", ", identifiers); - - return result; + return join (", ", identifiers); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/legacy.cpp b/src/legacy.cpp index be4039cf0..48beb99dd 100644 --- a/src/legacy.cpp +++ b/src/legacy.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/main.h b/src/main.h index ad1c60e88..1fd8dd628 100644 --- a/src/main.h +++ b/src/main.h @@ -83,21 +83,5 @@ std::string legacyCheckForDeprecatedVariables (); std::string legacyCheckForDeprecatedColumns (); void legacyAttributeMap (std::string&); -// list template -/////////////////////////////////////////////////////////////////////////////// -template void listDiff ( - const T& left, const T& right, T& leftOnly, T& rightOnly) -{ - leftOnly.clear (); - for (auto& l : left) - if (std::find (right.begin (), right.end (), l) == right.end ()) - leftOnly.push_back (l); - - rightOnly.clear (); - for (auto& r : right) - if (std::find (left.begin (), left.end (), r) == left.end ()) - rightOnly.push_back (r); -} - #endif //////////////////////////////////////////////////////////////////////////////// diff --git a/src/recur.cpp b/src/recur.cpp index 6ee2179fc..9a09f9a12 100644 --- a/src/recur.cpp +++ b/src/recur.cpp @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/rules.cpp b/src/rules.cpp index 16b19eb18..0bb86a161 100644 --- a/src/rules.cpp +++ b/src/rules.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/sort.cpp b/src/sort.cpp index 58c3e5cc9..055fc6f66 100644 --- a/src/sort.cpp +++ b/src/sort.cpp @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include extern Context context; @@ -52,8 +53,7 @@ void sort_tasks ( global_data = &data; // Split the key defs. - global_keys.clear (); - split (global_keys, keys, ','); + global_keys = split (keys, ','); // Only sort if necessary. if (order.size ()) diff --git a/src/text.cpp b/src/text.cpp index 707889ad9..c4b53fa22 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -170,33 +170,6 @@ std::string unquoteText (const std::string& input) return output; } -//////////////////////////////////////////////////////////////////////////////// -int longestWord (const std::string& input) -{ - int longest = 0; - int length = 0; - std::string::size_type i = 0; - int character; - - while ((character = utf8_next_char (input, i))) - { - if (character == ' ') - { - if (length > longest) - longest = length; - - length = 0; - } - else - length += mk_wcwidth (character); - } - - if (length > longest) - longest = length; - - return longest; -} - //////////////////////////////////////////////////////////////////////////////// int longestLine (const std::string& input) { @@ -312,32 +285,6 @@ bool extractLine ( return false; } -//////////////////////////////////////////////////////////////////////////////// -const std::string str_replace ( - std::string &str, - const std::string& search, - const std::string& replacement) -{ - std::string::size_type pos = 0; - while ((pos = str.find (search, pos)) != std::string::npos) - { - str.replace (pos, search.length (), replacement); - pos += replacement.length (); - } - - return str; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string str_replace ( - const std::string& str, - const std::string& search, - const std::string& replacement) -{ - std::string modified = str; - return str_replace (modified, search, replacement); -} - //////////////////////////////////////////////////////////////////////////////// const char* optionalBlankLine () { @@ -356,127 +303,6 @@ bool nontrivial (const std::string& input) return false; } -//////////////////////////////////////////////////////////////////////////////// -bool compare ( - const std::string& left, - const std::string& right, - bool sensitive /*= true*/) -{ - // Use strcasecmp if required. - if (!sensitive) - return strcasecmp (left.c_str (), right.c_str ()) == 0 ? true : false; - - // Otherwise, just use std::string::operator==. - return left == right; -} - -//////////////////////////////////////////////////////////////////////////////// -bool closeEnough ( - const std::string& reference, - const std::string& attempt, - unsigned int minLength /* = 0 */) -{ - // An exact match is accepted first. - if (compare (reference, attempt, false)) - return true; - - // A partial match will suffice. - if (attempt.length () < reference.length () && - attempt.length () >= minLength) - return compare (reference.substr (0, attempt.length ()), attempt, false); - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string::size_type find ( - const std::string& text, - const std::string& pattern, - bool sensitive /*= true*/) -{ - // Implement a sensitive find, which is really just a loop withing a loop, - // comparing lower-case versions of each character in turn. - if (!sensitive) - { - // Handle empty pattern. - const char* p = pattern.c_str (); - size_t len = pattern.length (); - if (len == 0) - return 0; - - // Evaluate these once, for performance reasons. - const char* t = text.c_str (); - const char* start = t; - const char* end = start + text.size (); - - for (; t <= end - len; ++t) - { - int diff = 0; - for (size_t i = 0; i < len; ++i) - if ((diff = tolower (t[i]) - tolower (p[i]))) - break; - - // diff == 0 means there was no break from the loop, which only occurs - // when a difference is detected. Therefore, the loop terminated, and - // diff is zero. - if (diff == 0) - return t - start; - } - - return std::string::npos; - } - - // Otherwise, just use std::string::find. - return text.find (pattern); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string::size_type find ( - const std::string& text, - const std::string& pattern, - std::string::size_type begin, - bool sensitive /*= true*/) -{ - // Implement a sensitive find, which is really just a loop withing a loop, - // comparing lower-case versions of each character in turn. - if (!sensitive) - { - // Handle empty pattern. - const char* p = pattern.c_str (); - size_t len = pattern.length (); - if (len == 0) - return 0; - - // Handle bad begin. - if (begin >= text.length ()) - return std::string::npos; - - // Evaluate these once, for performance reasons. - const char* start = text.c_str (); - const char* t = start + begin; - const char* end = start + text.size (); - - for (; t <= end - len; ++t) - { - int diff = 0; - for (size_t i = 0; i < len; ++i) - if ((diff = tolower (t[i]) - tolower (p[i]))) - break; - - // diff == 0 means there was no break from the loop, which only occurs - // when a difference is detected. Therefore, the loop terminated, and - // diff is zero. - if (diff == 0) - return t - start; - } - - return std::string::npos; - } - - // Otherwise, just use std::string::find. - return text.find (pattern, begin); -} - //////////////////////////////////////////////////////////////////////////////// // Return the length, in characters, of the input, subtracting color control // codes. @@ -536,74 +362,6 @@ const std::string obfuscateText (const std::string& input) return output.str (); } -//////////////////////////////////////////////////////////////////////////////// -const std::string format (std::string& value) -{ - return value; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string format (const char* value) -{ - std::string s (value); - return s; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string formatHex (int value) -{ - std::stringstream s; - s.setf (std::ios::hex, std::ios::basefield); - s << value; - return s.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string format (float value, int width, int precision) -{ - std::stringstream s; - s.width (width); - s.precision (precision); - if (0 < value && value < 1) - { - // For value close to zero, width - 2 (2 accounts for the first zero and - // the dot) is the number of digits after zero that are significant - double factor = 1; - for (int i = 2; i < width; i++) - factor *= 10; - value = roundf (value * factor) / factor; - } - s << value; - return s.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string format (double value, int width, int precision) -{ - std::stringstream s; - s.width (width); - s.precision (precision); - if (0 < value && value < 1) - { - // For value close to zero, width - 2 (2 accounts for the first zero and - // the dot) is the number of digits after zero that are significant - double factor = 1; - for (int i = 2; i < width; i++) - factor *= 10; - value = round (value * factor) / factor; - } - s << value; - return s.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string format (double value) -{ - std::stringstream s; - s << std::fixed << value; - return s.str (); -} - //////////////////////////////////////////////////////////////////////////////// void replace_positional ( std::string& fmt, diff --git a/src/text.h b/src/text.h index e2e858faa..26d6b23d6 100644 --- a/src/text.h +++ b/src/text.h @@ -35,7 +35,6 @@ // text.cpp, Non-UTF-8 aware. void wrapText (std::vector &, const std::string&, const int, bool); std::string unquoteText (const std::string&); -int longestWord (const std::string&); int longestLine (const std::string&); bool extractLine (std::string&, const std::string&, int, bool, unsigned int&); void split (std::set&, const std::string&, const char); @@ -43,53 +42,12 @@ void split (std::vector&, const std::string&, const char); void split (std::vector&, const std::string&, const std::string&); void join (std::string&, const std::string&, const std::vector&); void join (std::string&, const std::string&, const std::vector&); -const std::string str_replace (std::string&, const std::string&, const std::string&); -const std::string str_replace (const std::string&, const std::string&, const std::string&); const char* optionalBlankLine (); bool nontrivial (const std::string&); -bool compare (const std::string&, const std::string&, bool sensitive = true); -bool closeEnough (const std::string&, const std::string&, unsigned int minLength = 0); -std::string::size_type find (const std::string&, const std::string&, bool sensitive = true); -std::string::size_type find (const std::string&, const std::string&, std::string::size_type, bool sensitive = true); int strippedLength (const std::string&); const std::string obfuscateText (const std::string&); -const std::string format (std::string&); -const std::string format (const char*); -const std::string formatHex (int); -const std::string format (float, int, int); -const std::string format (double, int, int); -const std::string format (double); void replace_positional (std::string&, const std::string&, const std::string&); -template -const std::string format (T value) -{ - std::stringstream s; - s << value; - return s.str (); -} - -template -const std::string format (int fmt_num, const std::string& fmt, T arg) -{ - std::string output = fmt; - replace_positional (output, '{' + format (fmt_num) + '}', format (arg)); - return output; -} - -template -const std::string format (int fmt_num, const std::string& fmt, T arg, Args... args) -{ - const std::string fmt_replaced (format (fmt_num, fmt, arg)); - return format (fmt_num+1, fmt_replaced, args...); -} - -template -const std::string format (const std::string& fmt, Args... args) -{ - return format (1, fmt, args...); -} - std::string leftJustify (const int, const int); std::string leftJustify (const std::string&, const int); std::string rightJustifyZero (const int, const int); diff --git a/src/util.cpp b/src/util.cpp index f4eeb1565..fd37193d3 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////////////// #include -#include +#include // If is included, put it after , because it includes // , and therefore would ignore the _WITH_GETLINE. #ifdef FREEBSD @@ -163,41 +163,6 @@ std::string formatBytes (size_t bytes) return Lexer::commify (formatted); } -//////////////////////////////////////////////////////////////////////////////// -int autoComplete ( - const std::string& partial, - const std::vector& list, - std::vector& matches, - int minimum/* = 1*/) -{ - matches.clear (); - - // Handle trivial case. - unsigned int length = partial.length (); - if (length) - { - for (auto& item : list) - { - // An exact match is a special case. Assume there is only one exact match - // and return immediately. - if (partial == item) - { - matches.clear (); - matches.push_back (item); - return 1; - } - - // Maintain a list of partial matches. - else if (length >= (unsigned) minimum && - length <= item.length () && - partial == item.substr (0, length)) - matches.push_back (item); - } - } - - return matches.size (); -} - // Handle the generation of UUIDs on FreeBSD in a separate implementation // of the uuid () function, since the API is quite different from Linux's. // Also, uuid_unparse_lower is not needed on FreeBSD, because the string diff --git a/src/util.h b/src/util.h index 078fadbe6..a53e6e49b 100644 --- a/src/util.h +++ b/src/util.h @@ -43,7 +43,6 @@ bool confirm (const std::string&); int confirm4 (const std::string&); std::string formatBytes (size_t); -int autoComplete (const std::string&, const std::vector&, std::vector&, int minimum = 1); #ifndef HAVE_UUID_UNPARSE_LOWER void uuid_unparse_lower (uuid_t uu, char *out); From 0ed7fa8b2aaae4f89954cdf2a72034d722024c94 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 6 Dec 2016 07:23:25 -0500 Subject: [PATCH 0141/1455] calc: Migration to libshared --- src/calc.cpp | 3 +- src/commands/CmdBurndown.cpp | 7 ++--- src/text.cpp | 56 ------------------------------------ src/text.h | 6 ---- 4 files changed, 5 insertions(+), 67 deletions(-) diff --git a/src/calc.cpp b/src/calc.cpp index cf50b8695..55a7e4065 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include #include diff --git a/src/commands/CmdBurndown.cpp b/src/commands/CmdBurndown.cpp index 5be688997..ad43dd664 100644 --- a/src/commands/CmdBurndown.cpp +++ b/src/commands/CmdBurndown.cpp @@ -37,8 +37,8 @@ #include #include #include -#include -#include +#include +#include extern Context context; @@ -212,8 +212,7 @@ Chart::Chart (char type) // Set the title. std::vector words = context.cli2.getWords (); - std::string filter; - join (filter, " ", words); + auto filter = join (" ", words); _title = '(' + filter + ')'; } diff --git a/src/text.cpp b/src/text.cpp index c4b53fa22..0c859aeab 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -377,59 +377,3 @@ void replace_positional ( } //////////////////////////////////////////////////////////////////////////////// -std::string leftJustify (const int input, const int width) -{ - std::stringstream s; - s << input; - std::string output = s.str (); - return output + std::string (width - output.length (), ' '); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string leftJustify (const std::string& input, const int width) -{ - auto len = static_cast (utf8_text_width (input)); - - if (len == width) - return input; - - if (len > width) - return input.substr (0, width); - - return input + std::string (width - utf8_text_width (input), ' '); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string rightJustifyZero (const int input, const int width) -{ - std::stringstream s; - s << std::setw (width) << std::setfill ('0') << input; - return s.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string rightJustify (const int input, const int width) -{ - std::stringstream s; - s << std::setw (width) << std::setfill (' ') << input; - return s.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string rightJustify (const std::string& input, const int width) -{ - auto len = static_cast (utf8_text_width (input)); - - if (len == width) - return input; - - if (len > width) - return input.substr (0, width); - - return ((width > len) - ? std::string (width - len, ' ') - : "") - + input; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/text.h b/src/text.h index 26d6b23d6..dcefa7189 100644 --- a/src/text.h +++ b/src/text.h @@ -48,11 +48,5 @@ int strippedLength (const std::string&); const std::string obfuscateText (const std::string&); void replace_positional (std::string&, const std::string&, const std::string&); -std::string leftJustify (const int, const int); -std::string leftJustify (const std::string&, const int); -std::string rightJustifyZero (const int, const int); -std::string rightJustify (const int, const int); -std::string rightJustify (const std::string&, const int); - #endif //////////////////////////////////////////////////////////////////////////////// From 1bf2d0d20de32eebdef3770ed6a3d0b06f328ac9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 6 Dec 2016 07:25:41 -0500 Subject: [PATCH 0142/1455] text: Removed replace_positional --- src/text.cpp | 14 -------------- src/text.h | 1 - 2 files changed, 15 deletions(-) diff --git a/src/text.cpp b/src/text.cpp index 0c859aeab..ccd151410 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -363,17 +363,3 @@ const std::string obfuscateText (const std::string& input) } //////////////////////////////////////////////////////////////////////////////// -void replace_positional ( - std::string& fmt, - const std::string& from, - const std::string& to) -{ - std::string::size_type pos = 0; - while ((pos = fmt.find (from, pos)) != std::string::npos) - { - fmt.replace (pos, from.length (), to); - pos += to.length (); - } -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/text.h b/src/text.h index dcefa7189..b1dfef035 100644 --- a/src/text.h +++ b/src/text.h @@ -46,7 +46,6 @@ const char* optionalBlankLine (); bool nontrivial (const std::string&); int strippedLength (const std::string&); const std::string obfuscateText (const std::string&); -void replace_positional (std::string&, const std::string&, const std::string&); #endif //////////////////////////////////////////////////////////////////////////////// From 45e1622358179bf072058a30d654473f2be1986a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 6 Dec 2016 07:26:06 -0500 Subject: [PATCH 0143/1455] util: Removed formatBytes --- src/util.cpp | 14 -------------- src/util.h | 1 - 2 files changed, 15 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index fd37193d3..e6639ee2e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -149,20 +149,6 @@ int confirm4 (const std::string& question) return 0; } -//////////////////////////////////////////////////////////////////////////////// -// Convert a quantity in seconds to a more readable format. -std::string formatBytes (size_t bytes) -{ - char formatted[24]; - - if (bytes >= 995000000) snprintf (formatted, 24, "%.1f %s", (bytes / 1000000000.0), STRING_UTIL_GIBIBYTES); - else if (bytes >= 995000) snprintf (formatted, 24, "%.1f %s", (bytes / 1000000.0), STRING_UTIL_MEBIBYTES); - else if (bytes >= 995) snprintf (formatted, 24, "%.1f %s", (bytes / 1000.0), STRING_UTIL_KIBIBYTES); - else snprintf (formatted, 24, "%d %s", (int)bytes, STRING_UTIL_BYTES); - - return Lexer::commify (formatted); -} - // Handle the generation of UUIDs on FreeBSD in a separate implementation // of the uuid () function, since the API is quite different from Linux's. // Also, uuid_unparse_lower is not needed on FreeBSD, because the string diff --git a/src/util.h b/src/util.h index a53e6e49b..d3fb12047 100644 --- a/src/util.h +++ b/src/util.h @@ -42,7 +42,6 @@ // util.cpp bool confirm (const std::string&); int confirm4 (const std::string&); -std::string formatBytes (size_t); #ifndef HAVE_UUID_UNPARSE_LOWER void uuid_unparse_lower (uuid_t uu, char *out); From c12deb535e9ef7b443673150a3e2548af057b5d7 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 6 Dec 2016 07:28:50 -0500 Subject: [PATCH 0144/1455] util: Removed execute --- src/util.cpp | 149 --------------------------------------------------- src/util.h | 2 - 2 files changed, 151 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index e6639ee2e..2ba0ffd27 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -197,155 +197,6 @@ const std::string uuid () } #endif -//////////////////////////////////////////////////////////////////////////////// -// Run a binary with args, capturing output. -int execute ( - const std::string& executable, - const std::vector & args, - const std::string& input, - std::string& output) -{ - pid_t pid; - int pin[2], pout[2]; - fd_set rfds, wfds; - struct timeval tv; - int select_retval, read_retval, write_retval; - char buf[16384]; - unsigned int written; - const char* input_cstr = input.c_str (); - - if (signal (SIGPIPE, SIG_IGN) == SIG_ERR) // Handled locally with EPIPE. - throw std::string (std::strerror (errno)); - - if (pipe (pin) == -1) - throw std::string (std::strerror (errno)); - - if (pipe (pout) == -1) - throw std::string (std::strerror (errno)); - - if ((pid = fork ()) == -1) - throw std::string (std::strerror (errno)); - - if (pid == 0) - { - // This is only reached in the child - close (pin[1]); // Close the write end of the input pipe. - close (pout[0]); // Close the read end of the output pipe. - - // Parent writes to pin[1]. Set read end pin[0] as STDIN for child. - if (dup2 (pin[0], STDIN_FILENO) == -1) - throw std::string (std::strerror (errno)); - close (pin[0]); - - // Parent reads from pout[0]. Set write end pout[1] as STDOUT for child. - if (dup2 (pout[1], STDOUT_FILENO) == -1) - throw std::string (std::strerror (errno)); - close (pout[1]); - - // Add executable as argv[0] and NULL-terminate the array for execvp(). - char** argv = new char* [args.size () + 2]; - argv[0] = (char*) executable.c_str (); - for (unsigned int i = 0; i < args.size (); ++i) - argv[i+1] = (char*) args[i].c_str (); - - argv[args.size () + 1] = NULL; - _exit (execvp (executable.c_str (), argv)); - } - - // This is only reached in the parent - close (pin[0]); // Close the read end of the input pipe. - close (pout[1]); // Close the write end of the output pipe. - - if (input.size () == 0) - { - // Nothing to send to the child, close the pipe early. - close (pin[1]); - } - - output = ""; - read_retval = -1; - written = 0; - while (read_retval != 0 || input.size () != written) - { - FD_ZERO (&rfds); - if (read_retval != 0) - FD_SET (pout[0], &rfds); - - FD_ZERO (&wfds); - if (input.size () != written) - FD_SET (pin[1], &wfds); - - // On Linux, tv may be overwritten by select(). Reset it each time. - // NOTE: Timeout chosen arbitrarily - we don't time out execute() calls. - // select() is run over and over again unless the child exits or closes - // its pipes. - tv.tv_sec = 5; - tv.tv_usec = 0; - - select_retval = select (std::max (pout[0], pin[1]) + 1, &rfds, &wfds, NULL, &tv); - - if (select_retval == -1) - throw std::string (std::strerror (errno)); - - // Write data to child's STDIN - if (FD_ISSET (pin[1], &wfds)) - { - write_retval = write (pin[1], input_cstr + written, input.size () - written); - if (write_retval == -1) - { - if (errno == EPIPE) - { - // Child died (or closed the pipe) before reading all input. - // We don't really care; pretend we wrote it all. - write_retval = input.size () - written; - } - else - { - throw std::string (std::strerror (errno)); - } - } - written += write_retval; - - if (written == input.size ()) - { - // Let the child know that no more input is coming by closing the pipe. - close (pin[1]); - } - } - - // Read data from child's STDOUT - if (FD_ISSET (pout[0], &rfds)) - { - read_retval = read (pout[0], &buf, sizeof (buf) - 1); - if (read_retval == -1) - throw std::string (std::strerror (errno)); - - buf[read_retval] = '\0'; - output += buf; - } - } - - close (pout[0]); // Close the read end of the output pipe. - - int status = -1; - if (wait (&status) == -1) - throw std::string (std::strerror (errno)); - - if (WIFEXITED (status)) - { - status = WEXITSTATUS (status); - } - else - { - throw std::string ("Error: Could not get Hook exit status!"); - } - - if (signal (SIGPIPE, SIG_DFL) == SIG_ERR) // We're done, return to default. - throw std::string (std::strerror (errno)); - - return status; -} - // Collides with std::numeric_limits methods #undef max diff --git a/src/util.h b/src/util.h index d3fb12047..cc500723c 100644 --- a/src/util.h +++ b/src/util.h @@ -48,8 +48,6 @@ void uuid_unparse_lower (uuid_t uu, char *out); #endif const std::string uuid (); -int execute (const std::string&, const std::vector &, const std::string&, std::string&); - const std::string indentProject ( const std::string&, const std::string& whitespace = " ", From 6cdb0d4b950d9a5d65d85729156b4e9a57891fa9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 6 Dec 2016 07:32:19 -0500 Subject: [PATCH 0145/1455] util: Removed confirm --- src/commands/CmdDelete.cpp | 2 +- src/commands/CmdModify.cpp | 2 +- src/commands/CmdPrepend.cpp | 2 +- src/commands/CmdPurge.cpp | 2 +- src/util.cpp | 31 ------------------------------- src/util.h | 1 - 6 files changed, 4 insertions(+), 36 deletions(-) diff --git a/src/commands/CmdDelete.cpp b/src/commands/CmdDelete.cpp index 0bfc1c8ae..d2af38623 100644 --- a/src/commands/CmdDelete.cpp +++ b/src/commands/CmdDelete.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/commands/CmdModify.cpp b/src/commands/CmdModify.cpp index 352939479..e65b200bb 100644 --- a/src/commands/CmdModify.cpp +++ b/src/commands/CmdModify.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdPrepend.cpp b/src/commands/CmdPrepend.cpp index 87162c33b..835899da6 100644 --- a/src/commands/CmdPrepend.cpp +++ b/src/commands/CmdPrepend.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index 146754617..4a38c2b69 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include extern Context context; diff --git a/src/util.cpp b/src/util.cpp index 2ba0ffd27..50fc940cd 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -69,37 +69,6 @@ static void signal_handler (int s) } } -//////////////////////////////////////////////////////////////////////////////// -// Uses std::getline, because std::cin eats leading whitespace, and that means -// that if a newline is entered, std::cin eats it and never returns from the -// "std::cin >> answer;" line, but it does display the newline. This way, with -// std::getline, the newline can be detected, and the prompt re-written. -bool confirm (const std::string& question) -{ - std::vector options {STRING_UTIL_CONFIRM_YES, - STRING_UTIL_CONFIRM_NO}; - std::vector matches; - - signal (SIGINT, signal_handler); - - do - { - std::cout << question - << STRING_UTIL_CONFIRM_YN; - - std::string answer {""}; - std::getline (std::cin, answer); - context.debug ("STDIN '" + answer + '\''); - answer = std::cin.eof () ? STRING_UTIL_CONFIRM_NO : Lexer::lowerCase (Lexer::trim (answer)); - - autoComplete (answer, options, matches, 1); // Hard-coded 1. - } - while (! std::cin.eof () && matches.size () != 1); - - signal (SIGINT, SIG_DFL); - return matches.size () == 1 && matches[0] == STRING_UTIL_CONFIRM_YES ? true : false; -} - //////////////////////////////////////////////////////////////////////////////// // 0 = no // 1 = yes diff --git a/src/util.h b/src/util.h index cc500723c..404c0a1b9 100644 --- a/src/util.h +++ b/src/util.h @@ -40,7 +40,6 @@ #include // util.cpp -bool confirm (const std::string&); int confirm4 (const std::string&); #ifndef HAVE_UUID_UNPARSE_LOWER From 3c6ce4e0fc34b0ccda96c849858384ba6cffe498 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 7 Dec 2016 01:14:16 -0500 Subject: [PATCH 0146/1455] text: Removed local join/split implementation --- src/Config.cpp | 5 +- src/Msg.cpp | 6 +- src/commands/CmdCustom.cpp | 10 +- src/commands/CmdExec.cpp | 6 +- src/commands/CmdImport.cpp | 6 +- src/commands/CmdInfo.cpp | 3 +- src/commands/CmdUDAs.cpp | 4 +- src/dependency.cpp | 2 +- src/rules.cpp | 3 +- src/text.cpp | 241 +------------------------------------ src/text.h | 9 -- 11 files changed, 18 insertions(+), 277 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index 681a101ce..794dd5b16 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include @@ -437,8 +437,7 @@ void Config::parse (const std::string& input, int nest /* = 1 */) return; // Split the input into lines. - std::vector lines; - split (lines, input, "\n"); + auto lines = split (input, '\n'); // Parse each line. for (auto& line : lines) diff --git a/src/Msg.cpp b/src/Msg.cpp index bed357e11..86efa0930 100644 --- a/src/Msg.cpp +++ b/src/Msg.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include //////////////////////////////////////////////////////////////////////////////// void Msg::set (const std::string& name, const std::string& value) @@ -89,9 +89,7 @@ bool Msg::parse (const std::string& input) throw std::string ("ERROR: Malformed message"); // Parse header. - std::vector lines; - split (lines, input.substr (0, separator), '\n'); - for (auto& i : lines) + for (auto& i : split (input.substr (0, separator), '\n')) { auto delimiter = i.find (':'); if (delimiter == std::string::npos) diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index cc45fff3d..27a8eeb11 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -72,18 +73,15 @@ int CmdCustom::execute (std::string& output) std::string reportSort = context.config.get ("report." + _keyword + ".sort"); std::string reportFilter = context.config.get ("report." + _keyword + ".filter"); - std::vector columns; - split (columns, reportColumns, ','); + auto columns = split (reportColumns, ','); validateReportColumns (columns); - std::vector labels; - split (labels, reportLabels, ','); + auto labels = split (reportLabels, ','); if (columns.size () != labels.size () && labels.size () != 0) throw format (STRING_CMD_CUSTOM_MISMATCH, _keyword); - std::vector sortOrder; - split (sortOrder, reportSort, ','); + auto sortOrder = split (reportSort, ','); if (sortOrder.size () != 0 && sortOrder[0] != "none") validateSortColumns (sortOrder); diff --git a/src/commands/CmdExec.cpp b/src/commands/CmdExec.cpp index 2bfefebf7..d06f8b03e 100644 --- a/src/commands/CmdExec.cpp +++ b/src/commands/CmdExec.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include extern Context context; @@ -52,9 +52,7 @@ CmdExec::CmdExec () //////////////////////////////////////////////////////////////////////////////// int CmdExec::execute (std::string&) { - std::string command_line; - join (command_line, " ", context.cli2.getWords ()); - return system (command_line.c_str ()); + return system (join (" ", context.cli2.getWords ()).c_str ()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index 4ede977c0..657a438ff 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -147,10 +148,7 @@ int CmdImport::import (const std::string& input) // { ... } catch (std::string& e) { - std::vector lines; - split (lines, input, '\n'); - - for (auto& line : lines) + for (auto& line : split (input, '\n')) { if (line.length ()) { diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index 0f6273fb1..4134413ae 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -299,8 +299,7 @@ int CmdInfo::execute (std::string& output) task.getTags (tags); if (tags.size ()) { - std::string allTags; - join (allTags, " ", tags); + auto allTags = join (" ", tags); row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_TAGS); diff --git a/src/commands/CmdUDAs.cpp b/src/commands/CmdUDAs.cpp index 00091d904..685adeefd 100644 --- a/src/commands/CmdUDAs.cpp +++ b/src/commands/CmdUDAs.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -215,8 +216,7 @@ int CmdCompletionUDAs::execute (std::string& output) if (udas.size ()) { std::sort (udas.begin (), udas.end ()); - join (output, "\n", udas); - output += '\n'; + output = join ("\n", udas) + '\n'; } return 0; diff --git a/src/dependency.cpp b/src/dependency.cpp index b8e912579..de4f6ee94 100644 --- a/src/dependency.cpp +++ b/src/dependency.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/rules.cpp b/src/rules.cpp index 0bb86a161..c9715030e 100644 --- a/src/rules.cpp +++ b/src/rules.cpp @@ -67,8 +67,7 @@ void initializeColorRules () // Load the rule.precedence.color list, split it, then autocomplete against // the 'rules' vector loaded above. std::vector results; - std::vector precedence; - split (precedence, context.config.get ("rule.precedence.color"), ','); + auto precedence = split (context.config.get ("rule.precedence.color"), ','); for (const auto& p : precedence) { diff --git a/src/text.cpp b/src/text.cpp index ccd151410..1709e6a84 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -45,246 +46,6 @@ extern Context context; static const char* newline = "\n"; static const char* noline = ""; -/////////////////////////////////////////////////////////////////////////////// -void wrapText ( - std::vector & lines, - const std::string& text, - const int width, - bool hyphenate) -{ - std::string line; - unsigned int offset = 0; - while (extractLine (line, text, width, hyphenate, offset)) - lines.push_back (line); -} - -//////////////////////////////////////////////////////////////////////////////// -void split ( - std::set& results, - const std::string& input, - const char delimiter) -{ - results.clear (); - std::string::size_type start = 0; - std::string::size_type i; - while ((i = input.find (delimiter, start)) != std::string::npos) - { - results.insert (input.substr (start, i - start)); - start = i + 1; - } - - if (input.length ()) - results.insert (input.substr (start)); -} - -//////////////////////////////////////////////////////////////////////////////// -void split ( - std::vector& results, - const std::string& input, - const char delimiter) -{ - results.clear (); - std::string::size_type start = 0; - std::string::size_type i; - while ((i = input.find (delimiter, start)) != std::string::npos) - { - results.push_back (input.substr (start, i - start)); - start = i + 1; - } - - if (input.length ()) - results.push_back (input.substr (start)); -} - -//////////////////////////////////////////////////////////////////////////////// -void split ( - std::vector& results, - const std::string& input, - const std::string& delimiter) -{ - results.clear (); - std::string::size_type length = delimiter.length (); - - std::string::size_type start = 0; - std::string::size_type i; - while ((i = input.find (delimiter, start)) != std::string::npos) - { - results.push_back (input.substr (start, i - start)); - start = i + length; - } - - if (input.length ()) - results.push_back (input.substr (start)); -} - -//////////////////////////////////////////////////////////////////////////////// -void join ( - std::string& result, - const std::string& separator, - const std::vector& items) -{ - std::stringstream s; - unsigned int size = items.size (); - for (unsigned int i = 0; i < size; ++i) - { - s << items[i]; - if (i < size - 1) - s << separator; - } - - result = s.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -void join ( - std::string& result, - const std::string& separator, - const std::vector& items) -{ - std::stringstream s; - unsigned int size = items.size (); - for (unsigned int i = 0; i < size; ++i) - { - s << items[i]; - if (i < size - 1) - s << separator; - } - - result = s.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -// Remove enclosing balanced quotes. Assumes trimmed text. -std::string unquoteText (const std::string& input) -{ - std::string output = input; - - if (output.length () > 1) - { - char quote = output[0]; - if ((quote == '\'' || quote == '"') && - output[output.length () - 1] == quote) - return output.substr (1, output.length () - 2); - } - - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -int longestLine (const std::string& input) -{ - int longest = 0; - int length = 0; - std::string::size_type i = 0; - int character; - - while ((character = utf8_next_char (input, i))) - { - if (character == '\n') - { - if (length > longest) - longest = length; - - length = 0; - } - else - length += mk_wcwidth (character); - } - - if (length > longest) - longest = length; - - return longest; -} - -//////////////////////////////////////////////////////////////////////////////// -// Break UTF8 text into chunks no more than width characters. -bool extractLine ( - std::string& line, - const std::string& text, - int width, - bool hyphenate, - unsigned int& offset) -{ - // Terminate processing. - if (offset >= text.length ()) - return false; - - int line_length {0}; - int character {0}; - std::string::size_type lastWordEnd {std::string::npos}; - bool something {false}; - std::string::size_type cursor {offset}; - std::string::size_type prior_cursor {offset}; - while ((character = utf8_next_char (text, cursor))) - { - // Premature EOL. - if (character == '\n') - { - line = text.substr (offset, prior_cursor - offset); - offset = cursor; - return true; - } - - if (! Lexer::isWhitespace (character)) - { - something = true; - if (! text[cursor] || Lexer::isWhitespace (text[cursor])) - lastWordEnd = prior_cursor; - } - - line_length += mk_wcwidth (character); - - if (line_length >= width) - { - // Backtrack to previous word end. - if (lastWordEnd != std::string::npos) - { - // Eat one WS after lastWordEnd. - std::string::size_type lastBreak = lastWordEnd; - utf8_next_char (text, lastBreak); - - // Position offset at following char. - std::string::size_type nextStart = lastBreak; - utf8_next_char (text, nextStart); - - line = text.substr (offset, lastBreak - offset); - offset = nextStart; - return true; - } - - // No backtrack, possible hyphenation. - else if (hyphenate) - { - line = text.substr (offset, prior_cursor - offset) + '-'; - offset = prior_cursor; - return true; - } - - // No hyphenation, just truncation. - else - { - line = text.substr (offset, cursor - offset); - offset = cursor; - return true; - } - } - - // Hindsight. - prior_cursor = cursor; - } - - // Residual text. - if (something) - { - line = text.substr (offset, cursor - offset); - offset = cursor; - return true; - } - - return false; -} - //////////////////////////////////////////////////////////////////////////////// const char* optionalBlankLine () { diff --git a/src/text.h b/src/text.h index b1dfef035..de92b5263 100644 --- a/src/text.h +++ b/src/text.h @@ -33,15 +33,6 @@ #include // text.cpp, Non-UTF-8 aware. -void wrapText (std::vector &, const std::string&, const int, bool); -std::string unquoteText (const std::string&); -int longestLine (const std::string&); -bool extractLine (std::string&, const std::string&, int, bool, unsigned int&); -void split (std::set&, const std::string&, const char); -void split (std::vector&, const std::string&, const char); -void split (std::vector&, const std::string&, const std::string&); -void join (std::string&, const std::string&, const std::vector&); -void join (std::string&, const std::string&, const std::vector&); const char* optionalBlankLine (); bool nontrivial (const std::string&); int strippedLength (const std::string&); From fa420950a0b090aadfa4d9928eff81010cd607c0 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 7 Dec 2016 01:14:47 -0500 Subject: [PATCH 0147/1455] Tests: Removed migrated util tests --- test/util.t.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/test/util.t.cpp b/test/util.t.cpp index 9718b59d1..fb199dea9 100644 --- a/test/util.t.cpp +++ b/test/util.t.cpp @@ -42,26 +42,8 @@ int main (int, char**) unsetenv ("TASKDATA"); unsetenv ("TASKRC"); - // TODO bool confirm (const std::string&); // TODO int confirm4 (const std::string&); - // std::string formatBytes (size_t); - t.is (formatBytes (0), "0 B", "0 -> 0 B"); - - t.is (formatBytes (994), "994 B", "994 -> 994 B"); - t.is (formatBytes (995), "1.0 KiB", "995 -> 1.0 KiB"); - t.is (formatBytes (999), "1.0 KiB", "999 -> 1.0 KiB"); - t.is (formatBytes (1000), "1.0 KiB", "1000 -> 1.0 KiB"); - t.is (formatBytes (1001), "1.0 KiB", "1001 -> 1.0 KiB"); - - t.is (formatBytes (999999), "1.0 MiB", "999999 -> 1.0 MiB"); - t.is (formatBytes (1000000), "1.0 MiB", "1000000 -> 1.0 MiB"); - t.is (formatBytes (1000001), "1.0 MiB", "1000001 -> 1.0 MiB"); - - t.is (formatBytes (999999999), "1.0 GiB", "999999999 -> 1.0 GiB"); - t.is (formatBytes (1000000000), "1.0 GiB", "1000000000 -> 1.0 GiB"); - t.is (formatBytes (1000000001), "1.0 GiB", "1000000001 -> 1.0 GiB"); - // TODO const std::string uuid (); // TODO These are in feedback.cpp, not util.cpp. From 0dd4ed283645edd6fa72680af113291c556ec477 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 7 Dec 2016 01:15:01 -0500 Subject: [PATCH 0148/1455] Tests: Removed migrated text tests --- test/text.t.cpp | 323 +----------------------------------------------- 1 file changed, 1 insertion(+), 322 deletions(-) diff --git a/test/text.t.cpp b/test/text.t.cpp index cbcf19fab..651a04e78 100644 --- a/test/text.t.cpp +++ b/test/text.t.cpp @@ -37,205 +37,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { - UnitTest t (180); - - // void wrapText (std::vector & lines, const std::string& text, const int width, bool hyphenate) - std::string text = "This is a test of the line wrapping code."; - std::vector lines; - wrapText (lines, text, 10, true); - t.is (lines.size (), (size_t) 5, "wrapText 'This is a test of the line wrapping code.' -> total 5 lines"); - t.is (lines[0], "This is a", "wrapText line 0 -> 'This is a'"); - t.is (lines[1], "test of", "wrapText line 1 -> 'test of'"); - t.is (lines[2], "the line", "wrapText line 2 -> 'the line'"); - t.is (lines[3], "wrapping", "wrapText line 3 -> 'wrapping'"); - t.is (lines[4], "code.", "wrapText line 4 -> 'code.'"); - - text = "This ☺ is a test of utf8 line extraction."; - lines.clear (); - wrapText (lines, text, 7, true); - t.is (lines.size (), (size_t) 7, "wrapText 'This \\u263a is a test of utf8 line extraction.' -> total 7 lines"); - t.is (lines[0], "This ☺", "wrapText line 0 -> 'This \\u263a'"); - t.is (lines[1], "is a", "wrapText line 1 -> 'is a'"); - t.is (lines[2], "test of", "wrapText line 2 -> 'test of'"); - t.is (lines[3], "utf8", "wrapText line 3 -> 'utf8'"); - t.is (lines[4], "line", "wrapText line 4 -> 'line'"); - t.is (lines[5], "extrac-", "wrapText line 5 -> 'extrac-'"); - t.is (lines[6], "tion.", "wrapText line 6 -> 'tion.'"); - - text = "one two three\n four"; - lines.clear (); - wrapText (lines, text, 13, true); - t.is (lines.size (), (size_t) 2, "wrapText 'one two three\\n four' -> 2 lines"); - t.is (lines[0], "one two three", "wrapText line 0 -> 'one two three'"); - t.is (lines[1], " four", "wrapText line 1 -> ' four'"); - - // void extractLine (std::string& text, std::string& line, int length, bool hyphenate, unsigned int& offset) - text = "This ☺ is a test of utf8 line extraction."; - unsigned int offset = 0; - std::string line; - extractLine (line, text, 7, true, offset); - t.is (line, "This ☺", "extractLine 7 'This \\u263a is a test of utf8 line extraction.' -> 'This \\u263a'"); - - // void extractLine (std::string& text, std::string& line, int length, bool hyphenate, unsigned int& offset) - text = "line 1\nlengthy second line that exceeds width"; - offset = 0; - extractLine (line, text, 10, true, offset); - t.is (line, "line 1", "extractLine 10 'line 1\\nlengthy second line that exceeds width' -> 'line 1'"); - - extractLine (line, text, 10, true, offset); - t.is (line, "lengthy", "extractLine 10 'lengthy second line that exceeds width' -> 'lengthy'"); - - extractLine (line, text, 10, true, offset); - t.is (line, "second", "extractLine 10 'second line that exceeds width' -> 'second'"); - - extractLine (line, text, 10, true, offset); - t.is (line, "line that", "extractLine 10 'line that exceeds width' -> 'line that'"); - - extractLine (line, text, 10, true, offset); - t.is (line, "exceeds", "extractLine 10 'exceeds width' -> 'exceeds'"); - - extractLine (line, text, 10, true, offset); - t.is (line, "width", "extractLine 10 'width' -> 'width'"); - - t.notok (extractLine (line, text, 10, true, offset), "extractLine 10 '' -> ''"); - - text = "AAAAAAAAAABBBBBBBBBB"; - offset = 0; - extractLine (line, text, 10, true, offset); - t.is (line, "AAAAAAAAA-", "extractLine hyphenated unbreakable line 'AAAAAAAAAABBBBBBBBBB'/10 -> 'AAAAAAAAA-'"); - - extractLine (line, text, 10, true, offset); - t.is (line, "ABBBBBBBB-", "extractLine hyphenated unbreakable line 'AAAAAAAAAABBBBBBBBBB'/10 -> 'ABBBBBBBB-'"); - - extractLine (line, text, 10, true, offset); - t.is (line, "BB", "extractLine hyphenated unbreakable line 'AAAAAAAAAABBBBBBBBBB'/10 -> 'BB'"); - - text = "4444 333 "; - offset = 0; - while (extractLine (line, text, 9, true, offset)) - std::cout << "# line '" << line << "' offset " << offset << "\n"; - - // void split (std::vector& results, const std::string& input, const char delimiter) - std::vector items; - std::string unsplit = ""; - split (items, unsplit, '-'); - t.is (items.size (), (size_t) 0, "split '' '-' -> 0 items"); - - unsplit = "a"; - split (items, unsplit, '-'); - t.is (items.size (), (size_t) 1, "split 'a' '-' -> 1 item"); - t.is (items[0], "a", "split 'a' '-' -> 'a'"); - - split (items, unsplit, '-'); - t.is (items.size (), (size_t) 1, "split 'a' '-' -> 1 item"); - t.is (items[0], "a", "split 'a' '-' -> 'a'"); - - unsplit = "-"; - split (items, unsplit, '-'); - t.is (items.size (), (size_t) 2, "split '-' '-' -> '' ''"); - t.is (items[0], "", "split '-' '-' -> [0] ''"); - t.is (items[1], "", "split '-' '-' -> [1] ''"); - - unsplit = "-a-bc-def"; - split (items, unsplit, '-'); - t.is (items.size (), (size_t) 4, "split '-a-bc-def' '-' -> '' 'a' 'bc' 'def'"); - t.is (items[0], "", "split '-a-bc-def' '-' -> [0] ''"); - t.is (items[1], "a", "split '-a-bc-def' '-' -> [1] 'a'"); - t.is (items[2], "bc", "split '-a-bc-def' '-' -> [2] 'bc'"); - t.is (items[3], "def", "split '-a-bc-def' '-' -> [3] 'def'"); - - // void split (std::vector& results, const std::string& input, const std::string& delimiter) - unsplit = ""; - split (items, unsplit, "--"); - t.is (items.size (), (size_t) 0, "split '' '--' -> 0 items"); - - unsplit = "a"; - split (items, unsplit, "--"); - t.is (items.size (), (size_t) 1, "split 'a' '--' -> 1 item"); - t.is (items[0], "a", "split 'a' '-' -> 'a'"); - - unsplit = "--"; - split (items, unsplit, "--"); - t.is (items.size (), (size_t) 2, "split '-' '--' -> '' ''"); - t.is (items[0], "", "split '-' '-' -> [0] ''"); - t.is (items[1], "", "split '-' '-' -> [1] ''"); - - unsplit = "--a--bc--def"; - split (items, unsplit, "--"); - t.is (items.size (), (size_t) 4, "split '-a-bc-def' '--' -> '' 'a' 'bc' 'def'"); - t.is (items[0], "", "split '-a-bc-def' '--' -> [0] ''"); - t.is (items[1], "a", "split '-a-bc-def' '--' -> [1] 'a'"); - t.is (items[2], "bc", "split '-a-bc-def' '--' -> [2] 'bc'"); - t.is (items[3], "def", "split '-a-bc-def' '--' -> [3] 'def'"); - - unsplit = "one\ntwo\nthree"; - split (items, unsplit, "\n"); - t.is (items.size (), (size_t) 3, "split 'one\\ntwo\\nthree' -> 'one', 'two', 'three'"); - t.is (items[0], "one", "split 'one\\ntwo\\nthree' -> [0] 'one'"); - t.is (items[1], "two", "split 'one\\ntwo\\nthree' -> [1] 'two'"); - t.is (items[2], "three", "split 'one\\ntwo\\nthree' -> [2] 'three'"); - - // void join (std::string& result, const std::string& separator, const std::vector& items) - std::vector unjoined; - std::string joined; - - join (joined, "", unjoined); - t.is (joined.length (), (size_t) 0, "join -> length 0"); - t.is (joined, "", "join -> ''"); - - unjoined = {"", "a", "bc", "def"}; - join (joined, "", unjoined); - t.is (joined.length (), (size_t) 6, "join '' 'a' 'bc' 'def' -> length 6"); - t.is (joined, "abcdef", "join '' 'a' 'bc' 'def' -> 'abcdef'"); - - join (joined, "-", unjoined); - t.is (joined.length (), (size_t) 9, "join '' - 'a' - 'bc' - 'def' -> length 9"); - t.is (joined, "-a-bc-def", "join '' - 'a' - 'bc' - 'def' -> '-a-bc-def'"); - - // void join (std::string& result, const std::string& separator, const std::vector& items) - std::vector unjoined2; - - join (joined, "", unjoined2); - t.is (joined.length (), (size_t) 0, "join -> length 0"); - t.is (joined, "", "join -> ''"); - - unjoined2 = {0, 1, 2}; - join (joined, "", unjoined2); - t.is (joined.length (), (size_t) 3, "join 0 1 2 -> length 3"); - t.is (joined, "012", "join 0 1 2 -> '012'"); - - join (joined, "-", unjoined2); - t.is (joined.length (), (size_t) 5, "join 0 1 2 -> length 5"); - t.is (joined, "0-1-2", "join 0 1 2 -> '0-1-2'"); - - // std::string unquoteText (const std::string& text) - t.is (unquoteText (""), "", "unquoteText '' -> ''"); - t.is (unquoteText ("x"), "x", "unquoteText 'x' -> 'x'"); - t.is (unquoteText ("'x"), "'x", "unquoteText ''x' -> ''x'"); - t.is (unquoteText ("x'"), "x'", "unquoteText 'x'' -> 'x''"); - t.is (unquoteText ("\"x"), "\"x", "unquoteText '\"x' -> '\"x'"); - t.is (unquoteText ("x\""), "x\"", "unquoteText 'x\"' -> 'x\"'"); - t.is (unquoteText ("''"), "", "unquoteText '''' -> ''"); - t.is (unquoteText ("'''"), "'", "unquoteText ''''' -> '''"); - t.is (unquoteText ("\"\""), "", "unquoteText '\"\"' -> ''"); - t.is (unquoteText ("\"\"\""), "\"", "unquoteText '\"\"\"' -> '\"'"); - t.is (unquoteText ("''''"), "''", "unquoteText '''''' -> ''''"); - t.is (unquoteText ("\"\"\"\""), "\"\"", "unquoteText '\"\"\"\"' -> '\"\"'"); - t.is (unquoteText ("'\"\"'"), "\"\"", "unquoteText '''\"\"' -> '\"\"'"); - t.is (unquoteText ("\"''\""), "''", "unquoteText '\"''\"' -> ''''"); - t.is (unquoteText ("'x'"), "x", "unquoteText ''x'' -> 'x'"); - t.is (unquoteText ("\"x\""), "x", "unquoteText '\"x\"' -> 'x'"); - - // int longestWord (const std::string&) - t.is (longestWord (" "), 0, "longestWord ( ) --> 0"); - t.is (longestWord ("this is a test"), 4, "longestWord (this is a test) --> 4"); - t.is (longestWord ("this is a better test"), 6, "longestWord (this is a better test) --> 6"); - t.is (longestWord ("house Çirçös clown"), 6, "longestWord (house ...... clown) --> 6"); - - // int longestLine (const std::string&) - t.is (longestLine ("one two three four"), 18, "longestLine (one two three four) --> 18"); - t.is (longestLine ("one\ntwo three four"), 14, "longestLine (one\\ntwo three four) --> 14"); - t.is (longestLine ("one\ntwo\nthree\nfour"), 5, "longestLine (one\\ntwo\\nthree\\nfour) --> 5"); + UnitTest t (14); // bool nontrivial (const std::string&); t.notok (nontrivial (""), "nontrivial '' -> false"); @@ -248,66 +50,6 @@ int main (int, char**) t.ok (nontrivial (" \t\ta"), "nontrivial ' \\t\\ta' -> true"); t.ok (nontrivial ("a\t\t "), "nontrivial 'a\\t\\t ' -> true"); - // bool compare (const std::string&, const std::string&, bool caseless = false); - // Make sure degenerate cases are handled. - t.ok (compare ("", ""), "'' == ''"); - t.notok (compare ("foo", ""), "foo != ''"); - t.notok (compare ("", "foo"), "'' != foo"); - - // Make sure the default is case-sensitive. - t.ok (compare ("foo", "foo"), "foo == foo"); - t.notok (compare ("foo", "FOO"), "foo != foo"); - - // Test case-sensitive. - t.notok (compare ("foo", "xx", true), "foo != xx"); - - t.ok (compare ("foo", "foo", true), "foo == foo"); - t.notok (compare ("foo", "FOO", true), "foo != FOO"); - t.notok (compare ("FOO", "foo", true), "FOO != foo"); - t.ok (compare ("FOO", "FOO", true), "FOO == FOO"); - - // Test case-insensitive. - t.notok (compare ("foo", "xx", false), "foo != foo (caseless)"); - - t.ok (compare ("foo", "foo", false), "foo == foo (caseless)"); - t.ok (compare ("foo", "FOO", false), "foo == FOO (caseless)"); - t.ok (compare ("FOO", "foo", false), "FOO == foo (caseless)"); - t.ok (compare ("FOO", "FOO", false), "FOO == FOO (caseless)"); - - // std::string::size_type find (const std::string&, const std::string&, bool caseless = false); - // Make sure degenerate cases are handled. - t.is ((int) find ("foo", ""), (int) 0, "foo !contains ''"); - t.is ((int) find ("", "foo"), (int) std::string::npos, "'' !contains foo"); - - // Make sure the default is case-sensitive. - t.is ((int) find ("foo", "fo"), 0, "foo contains fo"); - t.is ((int) find ("foo", "FO"), (int) std::string::npos, "foo !contains fo"); - - // Test case-sensitive. - t.is ((int) find ("foo", "xx", true), (int) std::string::npos, "foo !contains xx"); - t.is ((int) find ("foo", "oo", true), 1, "foo contains oo"); - - t.is ((int) find ("foo", "fo", true), 0, "foo contains fo"); - t.is ((int) find ("foo", "FO", true), (int) std::string::npos, "foo !contains fo"); - t.is ((int) find ("FOO", "fo", true), (int) std::string::npos, "foo !contains fo"); - t.is ((int) find ("FOO", "FO", true), 0, "foo contains fo"); - - // Test case-insensitive. - t.is ((int) find ("foo", "xx", false), (int) std::string::npos, "foo !contains xx (caseless)"); - t.is ((int) find ("foo", "oo", false), 1, "foo contains oo (caseless)"); - - t.is ((int) find ("foo", "fo", false), 0, "foo contains fo (caseless)"); - t.is ((int) find ("foo", "FO", false), 0, "foo contains FO (caseless)"); - t.is ((int) find ("FOO", "fo", false), 0, "FOO contains fo (caseless)"); - t.is ((int) find ("FOO", "FO", false), 0, "FOO contains FO (caseless)"); - - // Test start offset. - t.is ((int) find ("one two three", "e", 3, true), (int) 11, "offset obeyed"); - t.is ((int) find ("one two three", "e", 11, true), (int) 11, "offset obeyed"); - - t.is ((int) find ("one two three", "e", 3, false), (int) 11, "offset obeyed"); - t.is ((int) find ("one two three", "e", 11, false), (int) 11, "offset obeyed"); - // int strippedLength (const std::string&); t.is (strippedLength (std::string ("")), 0, "strippedLength -> 0"); t.is (strippedLength (std::string ("abc")), 3, "strippedLength abc -> 3"); @@ -315,69 +57,6 @@ int main (int, char**) t.is (strippedLength (std::string ("\033[0m")), 0, "strippedLength ^[[0m -> 0"); t.is (strippedLength (std::string ("\033[1m\033[0m")), 0, "strippedLength ^[[1m^[[0m -> 0"); - // std::string format (char); - t.is (format ('A'), "A", "format ('A') -> A"); - - // std::string format (int); - t.is (format (0), "0", "format (0) -> 0"); - t.is (format (-1), "-1", "format (-1) -> -1"); - - // std::string formatHex (int); - t.is (formatHex (0), "0", "formatHex (0) -> 0"); - t.is (formatHex (10), "a", "formatHex (10) -> a"); - t.is (formatHex (123), "7b", "formatHex (123) -> 7b"); - - // std::string format (float, int, int); - t.is (format (0.12345678, 8, 4), " 0.1235", "format (0.12345678, 8, 4) -> __0.1235"); - - t.is (format (1.23456789, 8, 1), " 1", "format (1.23456789, 8, 1) -> _______1"); - t.is (format (1.23456789, 8, 2), " 1.2", "format (1.23456789, 8, 2) -> _____1.2"); - t.is (format (1.23456789, 8, 3), " 1.23", "format (1.23456789, 8, 3) -> ____1.23"); - t.is (format (1.23456789, 8, 4), " 1.235", "format (1.23456789, 8, 4) -> ___1.235"); - t.is (format (1.23456789, 8, 5), " 1.2346", "format (1.23456789, 8, 5) -> __1.2346"); - t.is (format (1.23456789, 8, 6), " 1.23457", "format (1.23456789, 8, 6) -> 1.23457"); - t.is (format (1.23456789, 8, 7), "1.234568", "format (1.23456789, 8, 7) -> 1.234568"); - t.is (format (1.23456789, 8, 8), "1.2345679", "format (1.23456789, 8, 8) -> 1.2345679"); - t.is (format (2444238.56789, 12, 11), "2444238.5679", "format (2444238.56789, 12, 11) -> 2444238.5679"); - - // std::string format (double, int, int); - - // std::string leftJustify (const std::string&, const int); - t.is (leftJustify (123, 3), "123", "leftJustify 123,3 -> '123'"); - t.is (leftJustify (123, 4), "123 ", "leftJustify 123,4 -> '123 '"); - t.is (leftJustify (123, 5), "123 ", "leftJustify 123,5 -> '123 '"); - - // std::string leftJustify (const std::string&, const int); - t.is (leftJustify ("foo", 3), "foo", "leftJustify foo,3 -> 'foo'"); - t.is (leftJustify ("foo", 4), "foo ", "leftJustify foo,4 -> 'foo '"); - t.is (leftJustify ("foo", 5), "foo ", "leftJustify foo,5 -> 'foo '"); - t.is (leftJustify ("föo", 5), "föo ", "leftJustify f:oo,5 -> 'f:oo '"); - - // When a string doesn't fit in the space necessary‥ - t.is (leftJustify ("foo", 2), "fo", "leftJustify foo,2 -> 'fo'"); - - // std::string rightJustify (const std::string&, const int); - t.is (rightJustify (123, 3), "123", "rightJustify 123,3 -> '123'"); - t.is (rightJustify (123, 4), " 123", "rightJustify 123,4 -> ' 123'"); - t.is (rightJustify (123, 5), " 123", "rightJustify 123,5 -> ' 123'"); - - // std::string rightJustify (const std::string&, const int); - t.is (rightJustify ("foo", 3), "foo", "rightJustify foo,3 -> 'foo'"); - t.is (rightJustify ("foo", 4), " foo", "rightJustify foo,4 -> ' foo'"); - t.is (rightJustify ("foo", 5), " foo", "rightJustify foo,5 -> ' foo'"); - t.is (rightJustify ("föo", 5), " föo", "rightJustify f:oo,5 -> ' f:oo'"); - - // bool closeEnough (const std::string&, const std::string&, unsigned int minLength = 0); - t.ok (closeEnough ("foobar", "foobar"), "closeEnough foobar == foobar"); - t.ok (closeEnough ("foobar", "foobar", 0), "closeEnough foobar == foobar,0"); - t.ok (closeEnough ("foobar", "foobar", 1), "closeEnough foobar == foobar,1"); - t.ok (closeEnough ("foobar", "foobar", 2), "closeEnough foobar == foobar,2"); - t.ok (closeEnough ("foobar", "foobar", 3), "closeEnough foobar == foobar,3"); - t.ok (closeEnough ("foobar", "foobar", 4), "closeEnough foobar == foobar,4"); - t.ok (closeEnough ("foobar", "foobar", 5), "closeEnough foobar == foobar,5"); - t.ok (closeEnough ("foobar", "foobar", 6), "closeEnough foobar == foobar,6"); - t.ok (closeEnough ("foobar", "foo", 3), "closeEnough foobar == foo,3"); - return 0; } From b38eae6930eefc94f8cc655ac144dc24447e9502 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 7 Dec 2016 01:18:25 -0500 Subject: [PATCH 0149/1455] Tests: Removed migrated autoComplete tests --- test/.gitignore | 1 - test/CMakeLists.txt | 10 +------ test/autocomplete.t.cpp | 66 ----------------------------------------- 3 files changed, 1 insertion(+), 76 deletions(-) delete mode 100644 test/autocomplete.t.cpp diff --git a/test/.gitignore b/test/.gitignore index b7c6be1a1..8cdb4cf86 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -3,7 +3,6 @@ *.data *.log *.runlog -autocomplete.t col.t color.t config.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index daf1442c0..1492287b0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,15 +14,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) -set (test_SRCS autocomplete.t col.t color.t config.t - msg.t nibbler.t t.t tdb2.t text.t util.t view.t - lexer.t iso8601d.t iso8601p.t eval.t dates.t - variant_add.t variant_and.t variant_cast.t variant_divide.t - variant_equal.t variant_exp.t variant_gt.t variant_gte.t - variant_inequal.t variant_lt.t variant_lte.t variant_match.t - variant_math.t variant_modulo.t variant_multiply.t - variant_nomatch.t variant_not.t variant_or.t variant_partial.t - variant_subtract.t variant_xor.t) +set (test_SRCS col.t color.t config.t msg.t nibbler.t t.t tdb2.t text.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t variant_inequal.t variant_lt.t variant_lte.t variant_match.t variant_math.t variant_modulo.t variant_multiply.t variant_nomatch.t variant_not.t variant_or.t variant_partial.t variant_subtract.t variant_xor.t) add_custom_target (test ./run_all --verbose DEPENDS ${test_SRCS} task_executable diff --git a/test/autocomplete.t.cpp b/test/autocomplete.t.cpp deleted file mode 100644 index 728df22aa..000000000 --- a/test/autocomplete.t.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -Context context; - -//////////////////////////////////////////////////////////////////////////////// -int main (int, char**) -{ - UnitTest t (8); - - // Ensure environment has no influence. - unsetenv ("TASKDATA"); - unsetenv ("TASKRC"); - - std::vector options {"abc", "abcd", "abcde", "bcdef", "cdefg"}; - std::vector matches; - int result = autoComplete ("", options, matches); - t.is (result, 0, "no match on empty string"); - - result = autoComplete ("x", options, matches); - t.is (result, 0, "no match on wrong string"); - - result = autoComplete ("abcd", options, matches); - t.is (result, 1, "exact match on 'abcd'"); - t.is (matches[0], "abcd", "exact match on 'abcd'"); - - result = autoComplete ("ab", options, matches); - t.is (result, 3, "partial match on 'ab'"); - t.is (matches[0], "abc", "partial match on 'abc'"); - t.is (matches[1], "abcd", "partial match on 'abcd'"); - t.is (matches[2], "abcde", "partial match on 'abcde'"); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// From 065fd8b6f1d42ba3043c5feaa59a0018b9db6eed Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 16:08:47 -0500 Subject: [PATCH 0150/1455] Task: Migrated unquoteText to Lexer::dequote --- src/Task.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Task.cpp b/src/Task.cpp index a284b849e..ed9544a8d 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -662,14 +662,17 @@ void Task::parseJSON (const json::object* root_obj) // TW-1274 Standardization. else if (i.first == "modification") { - ISO8601d d (unquoteText (i.second->dump ())); + auto text = i.second->dump (); + Lexer::dequote (text); + ISO8601d d (text); set ("modified", d.toEpochString ()); } // Dates are converted from ISO to epoch. else if (type == "date") { - std::string text = unquoteText (i.second->dump ()); + auto text = i.second->dump (); + Lexer::dequote (text); ISO8601d d (text); set (i.first, text == "" ? "" : d.toEpochString ()); } From 7a43183a3f96649deb284a3ce76a10c303ecb286 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 16:09:16 -0500 Subject: [PATCH 0151/1455] CLI2: Corrected str_replace calls --- src/CLI2.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/CLI2.cpp b/src/CLI2.cpp index 55dfc1aa5..1baf8ecc5 100644 --- a/src/CLI2.cpp +++ b/src/CLI2.cpp @@ -399,6 +399,7 @@ void CLI2::lexArguments () { bool quoted = Lexer::wasQuoted (_original_args[i].attribute ("raw")); + // Process single-token arguments. std::string lexeme; Lexer::Type type; Lexer lex (_original_args[i].attribute ("raw")); @@ -422,11 +423,13 @@ void CLI2::lexArguments () _args.push_back (a); } + + // Process muktiple-token arguments. else { std::string quote = "'"; std::string escaped = _original_args[i].attribute ("raw"); - str_replace (escaped, quote, "\\'"); + escaped = str_replace (escaped, quote, "\\'"); std::string::size_type cursor = 0; std::string word; From 0fecb26536db548b515e7fc7d50c7004f3307447 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 16:09:37 -0500 Subject: [PATCH 0152/1455] Task: Corrected str_replace calls --- src/Task.cpp | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/Task.cpp b/src/Task.cpp index ed9544a8d..a8a2e2ef1 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -1643,12 +1643,8 @@ void Task::validate_before (const std::string& left, const std::string& right) // ] -> &close; const std::string Task::encode (const std::string& value) const { - std::string modified = value; - - str_replace (modified, "[", "&open;"); - str_replace (modified, "]", "&close;"); - - return modified; + auto modified = str_replace (value, "[", "&open;"); + return str_replace (modified, "]", "&close;"); } //////////////////////////////////////////////////////////////////////////////// @@ -1661,18 +1657,11 @@ const std::string Task::encode (const std::string& value) const // : <- : const std::string Task::decode (const std::string& value) const { - if (value.find ('&') != std::string::npos) - { - std::string modified = value; + if (value.find ('&') == std::string::npos) + return value; - // Supported encodings. - str_replace (modified, "&open;", "["); - str_replace (modified, "&close;", "]"); - - return modified; - } - - return value; + auto modified = str_replace (value, "&open;", "["); + return str_replace (modified, "&close;", "]"); } //////////////////////////////////////////////////////////////////////////////// From 7041c466b4c916b38b6849df0d9d0977385345db Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 16:52:01 -0500 Subject: [PATCH 0153/1455] libshared: Updated to dfb31a41ced0fe48d98efa2b55689201d8e19667 --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index 2af7d0375..dfb31a41c 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit 2af7d037559f84450fffa812829fc553498a7ae4 +Subproject commit dfb31a41ced0fe48d98efa2b55689201d8e19667 From 9f36fdfe6599af11fab6f0f9ac23433b3f7038e5 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 16:53:28 -0500 Subject: [PATCH 0154/1455] Context: GC timing correction not always needed --- src/Context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Context.cpp b/src/Context.cpp index 61c591531..b4292ca7f 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -326,7 +326,7 @@ int Context::run () << " init:" << time_init_us << " load:" << time_load_us - << " gc:" << time_gc_us - time_load_us + << " gc:" << (time_gc_us > 0 ? time_gc_us - time_load_us : time_gc_us) << " filter:" << time_filter_us << " commit:" << time_commit_us << " sort:" << time_sort_us From a7d90fa1fa29d8054bc9770766ad0cde89b6e689 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 17:29:03 -0500 Subject: [PATCH 0155/1455] util: Migrated obfuscateText from text --- src/ViewTask.cpp | 2 +- src/ViewText.cpp | 2 +- src/text.cpp | 32 -------------------------------- src/text.h | 1 - src/util.cpp | 33 +++++++++++++++++++++++++++++++++ src/util.h | 1 + 6 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/ViewTask.cpp b/src/ViewTask.cpp index 4c2f9bff1..37e82e40f 100644 --- a/src/ViewTask.cpp +++ b/src/ViewTask.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/ViewText.cpp b/src/ViewText.cpp index c1d8455d8..98dc225ba 100644 --- a/src/ViewText.cpp +++ b/src/ViewText.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/text.cpp b/src/text.cpp index 1709e6a84..c1a4ffb0f 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -92,35 +92,3 @@ int strippedLength (const std::string& input) } //////////////////////////////////////////////////////////////////////////////// -const std::string obfuscateText (const std::string& input) -{ - std::stringstream output; - std::string::size_type i = 0; - int character; - bool inside = false; - - while ((character = utf8_next_char (input, i))) - { - if (inside) - { - output << (char) character; - - if (character == 'm') - inside = false; - } - else - { - if (character == 033) - inside = true; - - if (inside || character == ' ') - output << (char) character; - else - output << 'x'; - } - } - - return output.str (); -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/text.h b/src/text.h index de92b5263..3154a9ff6 100644 --- a/src/text.h +++ b/src/text.h @@ -36,7 +36,6 @@ const char* optionalBlankLine (); bool nontrivial (const std::string&); int strippedLength (const std::string&); -const std::string obfuscateText (const std::string&); #endif //////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.cpp b/src/util.cpp index 50fc940cd..b718b07f6 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -54,6 +54,7 @@ #include #include +#include #include #include @@ -283,3 +284,35 @@ std::string osName () } //////////////////////////////////////////////////////////////////////////////// +const std::string obfuscateText (const std::string& input) +{ + std::stringstream output; + std::string::size_type i = 0; + int character; + bool inside = false; + + while ((character = utf8_next_char (input, i))) + { + if (inside) + { + output << (char) character; + + if (character == 'm') + inside = false; + } + else + { + if (character == 033) + inside = true; + + if (inside || character == ' ') + output << (char) character; + else + output << 'x'; + } + } + + return output.str (); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.h b/src/util.h index 404c0a1b9..766e8ce73 100644 --- a/src/util.h +++ b/src/util.h @@ -61,6 +61,7 @@ const std::vector extractParents ( #endif std::string osName (); +const std::string obfuscateText (const std::string&); #endif //////////////////////////////////////////////////////////////////////////////// From 0027c9face0f2025a7b73aef663bb2c29d5702a4 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 17:34:50 -0500 Subject: [PATCH 0156/1455] util: Migrated nontrivial from text --- src/Hooks.cpp | 2 +- src/text.cpp | 12 ------------ src/text.h | 1 - src/util.cpp | 12 ++++++++++++ src/util.h | 1 + test/text.t.cpp | 13 +------------ test/util.t.cpp | 13 ++++++++++++- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Hooks.cpp b/src/Hooks.cpp index 109aa0490..f779b6b59 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/text.cpp b/src/text.cpp index c1a4ffb0f..3b64eea1c 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -52,18 +52,6 @@ const char* optionalBlankLine () return context.verbose ("blank") ? newline : noline; } -//////////////////////////////////////////////////////////////////////////////// -bool nontrivial (const std::string& input) -{ - std::string::size_type i = 0; - int character; - while ((character = utf8_next_char (input, i))) - if (! Lexer::isWhitespace (character)) - return true; - - return false; -} - //////////////////////////////////////////////////////////////////////////////// // Return the length, in characters, of the input, subtracting color control // codes. diff --git a/src/text.h b/src/text.h index 3154a9ff6..683cd825d 100644 --- a/src/text.h +++ b/src/text.h @@ -34,7 +34,6 @@ // text.cpp, Non-UTF-8 aware. const char* optionalBlankLine (); -bool nontrivial (const std::string&); int strippedLength (const std::string&); #endif diff --git a/src/util.cpp b/src/util.cpp index b718b07f6..ee6703cb7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -316,3 +316,15 @@ const std::string obfuscateText (const std::string& input) } //////////////////////////////////////////////////////////////////////////////// +bool nontrivial (const std::string& input) +{ + std::string::size_type i = 0; + int character; + while ((character = utf8_next_char (input, i))) + if (! Lexer::isWhitespace (character)) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.h b/src/util.h index 766e8ce73..bce568846 100644 --- a/src/util.h +++ b/src/util.h @@ -62,6 +62,7 @@ const std::vector extractParents ( std::string osName (); const std::string obfuscateText (const std::string&); +bool nontrivial (const std::string&); #endif //////////////////////////////////////////////////////////////////////////////// diff --git a/test/text.t.cpp b/test/text.t.cpp index 651a04e78..dd4d980ec 100644 --- a/test/text.t.cpp +++ b/test/text.t.cpp @@ -37,18 +37,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { - UnitTest t (14); - - // bool nontrivial (const std::string&); - t.notok (nontrivial (""), "nontrivial '' -> false"); - t.notok (nontrivial (" "), "nontrivial ' ' -> false"); - t.notok (nontrivial ("\t\t"), "nontrivial '\\t\\t' -> false"); - t.notok (nontrivial (" \t \t"), "nontrivial ' \\t \\t' -> false"); - t.ok (nontrivial ("a"), "nontrivial 'a' -> true"); - t.ok (nontrivial (" a"), "nontrivial ' a' -> true"); - t.ok (nontrivial ("a "), "nontrivial 'a ' -> true"); - t.ok (nontrivial (" \t\ta"), "nontrivial ' \\t\\ta' -> true"); - t.ok (nontrivial ("a\t\t "), "nontrivial 'a\\t\\t ' -> true"); + UnitTest t (5); // int strippedLength (const std::string&); t.is (strippedLength (std::string ("")), 0, "strippedLength -> 0"); diff --git a/test/util.t.cpp b/test/util.t.cpp index fb199dea9..03050d360 100644 --- a/test/util.t.cpp +++ b/test/util.t.cpp @@ -36,7 +36,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { - UnitTest t (22); + UnitTest t (19); // Ensure environment has no influence. unsetenv ("TASKDATA"); @@ -75,6 +75,17 @@ int main (int, char**) t.is (indentProject ("one.two"), " two", "indentProject 'one.two' -> ' two'"); t.is (indentProject ("one.two.three"), " three", "indentProject 'one.two.three' -> ' three'"); + // bool nontrivial (const std::string&); + t.notok (nontrivial (""), "nontrivial '' -> false"); + t.notok (nontrivial (" "), "nontrivial ' ' -> false"); + t.notok (nontrivial ("\t\t"), "nontrivial '\\t\\t' -> false"); + t.notok (nontrivial (" \t \t"), "nontrivial ' \\t \\t' -> false"); + t.ok (nontrivial ("a"), "nontrivial 'a' -> true"); + t.ok (nontrivial (" a"), "nontrivial ' a' -> true"); + t.ok (nontrivial ("a "), "nontrivial 'a ' -> true"); + t.ok (nontrivial (" \t\ta"), "nontrivial ' \\t\\ta' -> true"); + t.ok (nontrivial ("a\t\t "), "nontrivial 'a\\t\\t ' -> true"); + return 0; } From a0d88aaef8dde9b56c95273316baea1c88e218b1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 17:39:11 -0500 Subject: [PATCH 0157/1455] util: Migrated strippedLength from text --- src/text.cpp | 27 --------------------------- src/util.cpp | 27 +++++++++++++++++++++++++++ src/util.h | 1 + test/text.t.cpp | 9 +-------- test/util.t.cpp | 9 ++++++++- 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/text.cpp b/src/text.cpp index 3b64eea1c..214412026 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -53,30 +53,3 @@ const char* optionalBlankLine () } //////////////////////////////////////////////////////////////////////////////// -// Return the length, in characters, of the input, subtracting color control -// codes. -int strippedLength (const std::string& input) -{ - int length = input.length (); - bool inside = false; - int count = 0; - for (int i = 0; i < length; ++i) - { - if (inside) - { - if (input[i] == 'm') - inside = false; - } - else - { - if (input[i] == 033) - inside = true; - else - ++count; - } - } - - return count; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.cpp b/src/util.cpp index ee6703cb7..66dfefe5c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -328,3 +328,30 @@ bool nontrivial (const std::string& input) } //////////////////////////////////////////////////////////////////////////////// +// Return the length, in characters, of the input, subtracting color control +// codes. +int strippedLength (const std::string& input) +{ + int length = input.length (); + bool inside = false; + int count = 0; + for (int i = 0; i < length; ++i) + { + if (inside) + { + if (input[i] == 'm') + inside = false; + } + else + { + if (input[i] == 033) + inside = true; + else + ++count; + } + } + + return count; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.h b/src/util.h index bce568846..845e0668d 100644 --- a/src/util.h +++ b/src/util.h @@ -63,6 +63,7 @@ const std::vector extractParents ( std::string osName (); const std::string obfuscateText (const std::string&); bool nontrivial (const std::string&); +int strippedLength (const std::string&); #endif //////////////////////////////////////////////////////////////////////////////// diff --git a/test/text.t.cpp b/test/text.t.cpp index dd4d980ec..b188d4bc3 100644 --- a/test/text.t.cpp +++ b/test/text.t.cpp @@ -37,14 +37,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { - UnitTest t (5); - - // int strippedLength (const std::string&); - t.is (strippedLength (std::string ("")), 0, "strippedLength -> 0"); - t.is (strippedLength (std::string ("abc")), 3, "strippedLength abc -> 3"); - t.is (strippedLength (std::string ("one\033[5;38;255mtwo\033[0mthree")), 11, "strippedLength one^[[5;38;255mtwo^[[0mthree -> 11"); - t.is (strippedLength (std::string ("\033[0m")), 0, "strippedLength ^[[0m -> 0"); - t.is (strippedLength (std::string ("\033[1m\033[0m")), 0, "strippedLength ^[[1m^[[0m -> 0"); + UnitTest t (0); return 0; } diff --git a/test/util.t.cpp b/test/util.t.cpp index 03050d360..5c8104a71 100644 --- a/test/util.t.cpp +++ b/test/util.t.cpp @@ -36,7 +36,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { - UnitTest t (19); + UnitTest t (24); // Ensure environment has no influence. unsetenv ("TASKDATA"); @@ -86,6 +86,13 @@ int main (int, char**) t.ok (nontrivial (" \t\ta"), "nontrivial ' \\t\\ta' -> true"); t.ok (nontrivial ("a\t\t "), "nontrivial 'a\\t\\t ' -> true"); + // int strippedLength (const std::string&); + t.is (strippedLength (std::string ("")), 0, "strippedLength -> 0"); + t.is (strippedLength (std::string ("abc")), 3, "strippedLength abc -> 3"); + t.is (strippedLength (std::string ("one\033[5;38;255mtwo\033[0mthree")), 11, "strippedLength one^[[5;38;255mtwo^[[0mthree -> 11"); + t.is (strippedLength (std::string ("\033[0m")), 0, "strippedLength ^[[0m -> 0"); + t.is (strippedLength (std::string ("\033[1m\033[0m")), 0, "strippedLength ^[[1m^[[0m -> 0"); + return 0; } From eb1e35e84b149d5bc5086b2ae56358c607d931d3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 17:40:40 -0500 Subject: [PATCH 0158/1455] Tests: Eliminated empty text.t test --- test/.gitignore | 1 - test/CMakeLists.txt | 2 +- test/text.t.cpp | 45 --------------------------------------------- 3 files changed, 1 insertion(+), 47 deletions(-) delete mode 100644 test/text.t.cpp diff --git a/test/.gitignore b/test/.gitignore index 8cdb4cf86..c0a96c1c5 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -16,7 +16,6 @@ nibbler.t t.t taskmod.t tdb2.t -text.t uri.t util.t variant_add.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1492287b0..3dc02f2ba 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,7 +14,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) -set (test_SRCS col.t color.t config.t msg.t nibbler.t t.t tdb2.t text.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t variant_inequal.t variant_lt.t variant_lte.t variant_match.t variant_math.t variant_modulo.t variant_multiply.t variant_nomatch.t variant_not.t variant_or.t variant_partial.t variant_subtract.t variant_xor.t) +set (test_SRCS col.t color.t config.t msg.t nibbler.t t.t tdb2.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t variant_inequal.t variant_lt.t variant_lte.t variant_match.t variant_math.t variant_modulo.t variant_multiply.t variant_nomatch.t variant_not.t variant_or.t variant_partial.t variant_subtract.t variant_xor.t) add_custom_target (test ./run_all --verbose DEPENDS ${test_SRCS} task_executable diff --git a/test/text.t.cpp b/test/text.t.cpp deleted file mode 100644 index b188d4bc3..000000000 --- a/test/text.t.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -Context context; - -//////////////////////////////////////////////////////////////////////////////// -int main (int, char**) -{ - UnitTest t (0); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// From 87757fb36fd7f63cd470989e774b1dacaa70d88e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 17:46:06 -0500 Subject: [PATCH 0159/1455] util: Migrated optionalBlankLine from text --- src/columns/ColString.cpp | 2 +- src/commands/CmdCalendar.cpp | 2 +- src/commands/CmdColumns.cpp | 2 +- src/commands/CmdCommands.cpp | 2 +- src/commands/CmdContext.cpp | 2 +- src/commands/CmdCustom.cpp | 2 +- src/commands/CmdHistory.cpp | 2 +- src/commands/CmdInfo.cpp | 2 +- src/commands/CmdLogo.cpp | 2 +- src/commands/CmdReports.cpp | 2 +- src/commands/CmdTags.cpp | 2 +- src/text.cpp | 9 --------- src/text.h | 2 -- src/util.cpp | 9 +++++++++ src/util.h | 1 + 15 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/columns/ColString.cpp b/src/columns/ColString.cpp index 5befb51e5..5313b0ad0 100644 --- a/src/columns/ColString.cpp +++ b/src/columns/ColString.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdCalendar.cpp b/src/commands/CmdCalendar.cpp index 6bc259051..cd7ff484c 100644 --- a/src/commands/CmdCalendar.cpp +++ b/src/commands/CmdCalendar.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/commands/CmdColumns.cpp b/src/commands/CmdColumns.cpp index 8772a9e85..6f2c94f4f 100644 --- a/src/commands/CmdColumns.cpp +++ b/src/commands/CmdColumns.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/commands/CmdCommands.cpp b/src/commands/CmdCommands.cpp index 728b9c50c..f11a147f2 100644 --- a/src/commands/CmdCommands.cpp +++ b/src/commands/CmdCommands.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdContext.cpp b/src/commands/CmdContext.cpp index 057b8d6f8..c4de69c88 100644 --- a/src/commands/CmdContext.cpp +++ b/src/commands/CmdContext.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include extern Context context; diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index 27a8eeb11..cadf326c5 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdHistory.cpp b/src/commands/CmdHistory.cpp index 2d7e5b4c7..a8d71eb7f 100644 --- a/src/commands/CmdHistory.cpp +++ b/src/commands/CmdHistory.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index 4134413ae..9aa8b9b6c 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdLogo.cpp b/src/commands/CmdLogo.cpp index 1c25fbc06..a55b457fa 100644 --- a/src/commands/CmdLogo.cpp +++ b/src/commands/CmdLogo.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdReports.cpp b/src/commands/CmdReports.cpp index 0fa52cb0c..75dd585b4 100644 --- a/src/commands/CmdReports.cpp +++ b/src/commands/CmdReports.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/commands/CmdTags.cpp b/src/commands/CmdTags.cpp index 5f75b85b3..4187a03dc 100644 --- a/src/commands/CmdTags.cpp +++ b/src/commands/CmdTags.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include extern Context context; diff --git a/src/text.cpp b/src/text.cpp index 214412026..85290a073 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -43,13 +43,4 @@ extern Context context; -static const char* newline = "\n"; -static const char* noline = ""; - -//////////////////////////////////////////////////////////////////////////////// -const char* optionalBlankLine () -{ - return context.verbose ("blank") ? newline : noline; -} - //////////////////////////////////////////////////////////////////////////////// diff --git a/src/text.h b/src/text.h index 683cd825d..16b91c3c1 100644 --- a/src/text.h +++ b/src/text.h @@ -33,8 +33,6 @@ #include // text.cpp, Non-UTF-8 aware. -const char* optionalBlankLine (); -int strippedLength (const std::string&); #endif //////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.cpp b/src/util.cpp index 66dfefe5c..e001c2e4c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -60,6 +60,9 @@ extern Context context; +static const char* newline = "\n"; +static const char* noline = ""; + //////////////////////////////////////////////////////////////////////////////// static void signal_handler (int s) { @@ -355,3 +358,9 @@ int strippedLength (const std::string& input) } //////////////////////////////////////////////////////////////////////////////// +const char* optionalBlankLine () +{ + return context.verbose ("blank") ? newline : noline; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.h b/src/util.h index 845e0668d..c1ed270ef 100644 --- a/src/util.h +++ b/src/util.h @@ -64,6 +64,7 @@ std::string osName (); const std::string obfuscateText (const std::string&); bool nontrivial (const std::string&); int strippedLength (const std::string&); +const char* optionalBlankLine (); #endif //////////////////////////////////////////////////////////////////////////////// From b2ad9e96bd6db1f95b05d4470bb757f71c1b12ae Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 17:51:44 -0500 Subject: [PATCH 0160/1455] text: Eliminated module --- src/CMakeLists.txt | 1 - src/columns/ColStart.cpp | 1 - src/commands/CmdImport.cpp | 1 - src/commands/CmdProjects.cpp | 1 - src/commands/CmdStats.cpp | 1 - src/commands/CmdSummary.cpp | 1 - src/commands/CmdUDAs.cpp | 1 - src/rules.cpp | 1 - src/text.cpp | 46 ------------------------------------ src/text.h | 38 ----------------------------- src/util.cpp | 1 - 11 files changed, 93 deletions(-) delete mode 100644 src/text.cpp delete mode 100644 src/text.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3d4e5f9d3..564c68f73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,7 +32,6 @@ add_library (task CLI2.cpp CLI2.h recur.cpp rules.cpp sort.cpp - text.cpp text.h util.cpp util.h) add_library (libshared libshared/src/Datetime.cpp libshared/src/Datetime.h diff --git a/src/columns/ColStart.cpp b/src/columns/ColStart.cpp index fdb3fd600..df807d045 100644 --- a/src/columns/ColStart.cpp +++ b/src/columns/ColStart.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index 657a438ff..f5f1e98a5 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/src/commands/CmdProjects.cpp b/src/commands/CmdProjects.cpp index 8d7defea4..7606472c4 100644 --- a/src/commands/CmdProjects.cpp +++ b/src/commands/CmdProjects.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/src/commands/CmdStats.cpp b/src/commands/CmdStats.cpp index 0ef70197c..5d2df249a 100644 --- a/src/commands/CmdStats.cpp +++ b/src/commands/CmdStats.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index 1e45e6189..85272c11a 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/src/commands/CmdUDAs.cpp b/src/commands/CmdUDAs.cpp index 685adeefd..f1ca5023c 100644 --- a/src/commands/CmdUDAs.cpp +++ b/src/commands/CmdUDAs.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include diff --git a/src/rules.cpp b/src/rules.cpp index c9715030e..0ebd1f10d 100644 --- a/src/rules.cpp +++ b/src/rules.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/src/text.cpp b/src/text.cpp deleted file mode 100644 index 85290a073..000000000 --- a/src/text.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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; - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/text.h b/src/text.h deleted file mode 100644 index 16b91c3c1..000000000 --- a/src/text.h +++ /dev/null @@ -1,38 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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_TEXT -#define INCLUDED_TEXT - -#include -#include -#include -#include - -// text.cpp, Non-UTF-8 aware. - -#endif -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.cpp b/src/util.cpp index e001c2e4c..bd330eceb 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -53,7 +53,6 @@ #include #include -#include #include #include #include From a456228e985580918f9bdfe7e674312845dedbf4 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 19:56:59 -0500 Subject: [PATCH 0161/1455] libshared: Updated to 9685a22c90ca6f832748f8c71bae3cfad352bc64 --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index dfb31a41c..9685a22c9 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit dfb31a41ced0fe48d98efa2b55689201d8e19667 +Subproject commit 9685a22c90ca6f832748f8c71bae3cfad352bc64 From cdfd92ed9b6aaaab0316dad031be1b8561e22841 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 20:00:30 -0500 Subject: [PATCH 0162/1455] Task: Migrated from Nibbler to Pig --- src/Task.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Task.cpp b/src/Task.cpp index a8a2e2ef1..e8b82905c 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -39,7 +39,7 @@ #include #ifdef PRODUCT_TASKWARRIOR #include -#include +#include #endif #include #ifdef PRODUCT_TASKWARRIOR @@ -576,24 +576,24 @@ void Task::parse (const std::string& input) if (input[0] == '[') { - Nibbler n (input); + Pig pig (input); std::string line; - if (n.skip ('[') && - n.getUntil (']', line) && - n.skip (']') && - (n.skip ('\n') || n.depleted ())) + if (pig.skip ('[') && + pig.getUntil (']', line) && + pig.skip (']') && + (pig.skip ('\n') || pig.eos ())) { if (line.length () == 0) throw std::string (STRING_RECORD_EMPTY); - Nibbler nl (line); + Pig attLine (line); std::string name; std::string value; - while (!nl.depleted ()) + while (!attLine.eos ()) { - if (nl.getUntil (':', name) && - nl.skip (':') && - nl.getQuoted ('"', value)) + if (attLine.getUntil (':', name) && + attLine.skip (':') && + attLine.getQuoted ('"', value)) { #ifdef PRODUCT_TASKWARRIOR legacyAttributeMap (name); @@ -605,11 +605,11 @@ void Task::parse (const std::string& input) data[name] = decode (json::decode (value)); } - nl.skip (' '); + attLine.skip (' '); } std::string remainder; - nl.getUntilEOS (remainder); + attLine.getRemainder (remainder); if (remainder.length ()) throw std::string (STRING_RECORD_JUNK_AT_EOL); } From f6ae39cb8222980df202634a7d771c841d6fec22 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 20:33:13 -0500 Subject: [PATCH 0163/1455] Msg: Migrated to use libshared --- src/CMakeLists.txt | 2 +- src/Msg.cpp | 107 -------------------------------------------- src/Msg.h | 53 ---------------------- test/.gitignore | 1 - test/CMakeLists.txt | 2 +- test/msg.t.cpp | 73 ------------------------------ 6 files changed, 2 insertions(+), 236 deletions(-) delete mode 100644 src/Msg.cpp delete mode 100644 src/Msg.h delete mode 100644 test/msg.t.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 564c68f73..d6ae2e22a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,7 +17,6 @@ add_library (task CLI2.cpp CLI2.h Hooks.cpp Hooks.h ISO8601.cpp ISO8601.h Lexer.cpp Lexer.h - Msg.cpp Msg.h Nibbler.cpp Nibbler.h TDB2.cpp TDB2.h Task.cpp Task.h @@ -38,6 +37,7 @@ add_library (libshared libshared/src/Datetime.cpp libshared/src/Datetime.h libshared/src/Duration.cpp libshared/src/Duration.h libshared/src/FS.cpp libshared/src/FS.h libshared/src/JSON.cpp libshared/src/JSON.h + libshared/src/Msg.cpp libshared/src/Msg.h libshared/src/Pig.cpp libshared/src/Pig.h libshared/src/RX.cpp libshared/src/RX.h libshared/src/Table.cpp libshared/src/Table.h diff --git a/src/Msg.cpp b/src/Msg.cpp deleted file mode 100644 index 86efa0930..000000000 --- a/src/Msg.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -//////////////////////////////////////////////////////////////////////////////// -void Msg::set (const std::string& name, const std::string& value) -{ - _header[name] = value; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Msg::get (const std::string& name) const -{ - auto i = _header.find (name); - if (i != _header.end ()) - return i->second; - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -void Msg::setPayload (const std::string& payload) -{ - _payload = payload; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Msg::getPayload () const -{ - return _payload; -} - -//////////////////////////////////////////////////////////////////////////////// -std::vector Msg::all () const -{ - std::vector names; - for (auto& i : _header) - names.push_back (i.first); - - return names; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Msg::serialize () const -{ - std::string output; - for (auto& i : _header) - output += i.first + ": " + i.second + '\n'; - - output += '\n' + _payload + '\n'; - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Msg::parse (const std::string& input) -{ - _header.clear (); - _payload = ""; - - auto separator = input.find ("\n\n"); - if (separator == std::string::npos) - throw std::string ("ERROR: Malformed message"); - - // Parse header. - for (auto& i : split (input.substr (0, separator), '\n')) - { - auto delimiter = i.find (':'); - if (delimiter == std::string::npos) - throw std::string ("ERROR: Malformed message header '") + i + '\''; - - _header[Lexer::trim (i.substr (0, delimiter))] = Lexer::trim (i.substr (delimiter + 1)); - } - - // Parse payload. - _payload = input.substr (separator + 2); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Msg.h b/src/Msg.h deleted file mode 100644 index 72736b6d2..000000000 --- a/src/Msg.h +++ /dev/null @@ -1,53 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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_MSG -#define INCLUDED_MSG - -#include -#include -#include - -class Msg -{ -public: - void set (const std::string&, const std::string&); - std::string get (const std::string&) const; - - void setPayload (const std::string&); - std::string getPayload () const; - - std::vector all () const; - std::string serialize () const; - bool parse (const std::string&); - -private: - std::map _header {}; - std::string _payload {""}; -}; - -#endif - diff --git a/test/.gitignore b/test/.gitignore index c0a96c1c5..0d38f628a 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -11,7 +11,6 @@ eval.t iso8601d.t iso8601p.t lexer.t -msg.t nibbler.t t.t taskmod.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3dc02f2ba..20a3c0512 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,7 +14,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) -set (test_SRCS col.t color.t config.t msg.t nibbler.t t.t tdb2.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t variant_inequal.t variant_lt.t variant_lte.t variant_match.t variant_math.t variant_modulo.t variant_multiply.t variant_nomatch.t variant_not.t variant_or.t variant_partial.t variant_subtract.t variant_xor.t) +set (test_SRCS col.t color.t config.t nibbler.t t.t tdb2.t util.t view.t lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t variant_inequal.t variant_lt.t variant_lte.t variant_match.t variant_math.t variant_modulo.t variant_multiply.t variant_nomatch.t variant_not.t variant_or.t variant_partial.t variant_subtract.t variant_xor.t) add_custom_target (test ./run_all --verbose DEPENDS ${test_SRCS} task_executable diff --git a/test/msg.t.cpp b/test/msg.t.cpp deleted file mode 100644 index dd5f469dd..000000000 --- a/test/msg.t.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -Context context; - -//////////////////////////////////////////////////////////////////////////////// -int main (int, char**) -{ - UnitTest t (13); - - Msg m; - t.is (m.serialize (), "\n\n", "Msg::serialize '' --> '\\n\\n'"); - - m.set ("name", "value"); - t.is (m.serialize (), "name: value\n\n\n", - "Msg::serialize 1 var"); - - m.set ("foo", "bar"); - t.is (m.serialize (), "foo: bar\nname: value\n\n\n", - "Msg::serialize 2 vars"); - - m.setPayload ("payload"); - t.is (m.serialize (), "foo: bar\nname: value\n\npayload\n", - "Msg::serialize 2 vars + payload"); - - Msg m2; - t.ok (m2.parse ("foo: bar\nname: value\n\npayload\n"), - "Msg::parse ok"); - t.is (m2.get ("foo"), "bar", "Msg::get"); - t.is (m2.get ("name"), "value", "Msg::get"); - t.is (m2.getPayload (), "payload\n", "Msg::getPayload"); - - Msg m3; - t.ok (m3.parse ("foo:bar\nname: value\n\npayload\n"), - "Msg::parse ok"); - t.is (m3.get ("foo"), "bar", "Msg::get"); - t.is (m3.get ("name"), "value", "Msg::get"); - t.is (m3.getPayload (), "payload\n", "Msg::getPayload"); - t.ok (m3.all () == std::vector {"foo", "name"}, - "Msg::all --> {'foo', 'name'}"); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// From abd4cfc4edd7f53324ec156510cde2b3f6105692 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 20:52:54 -0500 Subject: [PATCH 0164/1455] DOM: Migrated from Nibbler to Lexer --- src/DOM.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/DOM.cpp b/src/DOM.cpp index 88b6c3c65..74f063bbe 100644 --- a/src/DOM.cpp +++ b/src/DOM.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -193,26 +194,25 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) auto elements = split (name, '.'); Task ref (task); - Nibbler n (elements[0]); - n.save (); - int id; - std::string uuid; - - // If elements[0] is a UUID, load that task (if necessary), and clobber ref. - if (n.getPartialUUID (uuid) && n.depleted ()) + Lexer lexer (elements[0]); + std::string token; + Lexer::Type type; + if (lexer.token (token, type)) { - if (uuid != ref.get ("uuid")) - context.tdb2.get (uuid, ref); - - // Eat elements[0]/UUID. - elements.erase (elements.begin ()); - } - else - { - // If elements[0] is a ID, load that task (if necessary), and clobber ref. - if (n.getInt (id) && n.depleted ()) + if (type == Lexer::Type::uuid && + token.length () == elements[0].length ()) { - if (id != ref.id) + if (token != ref.get ("uuid")) + context.tdb2.get (token, ref); + + // Eat elements[0]/UUID. + elements.erase (elements.begin ()); + } + else if (type == Lexer::Type::number && + token.find ('.') == std::string::npos) + { + auto id = strtol (token.c_str (), NULL, 10); + if (id && id != ref.id) context.tdb2.get (id, ref); // Eat elements[0]/ID. From d9a3be999349e7044c33cd4b08181d6ed2477863 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 21:03:15 -0500 Subject: [PATCH 0165/1455] Variant: Converted from ISO8601p to Duration --- src/Variant.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Variant.cpp b/src/Variant.cpp index a4a287515..0bcdbe898 100644 --- a/src/Variant.cpp +++ b/src/Variant.cpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -1730,10 +1732,10 @@ Variant::operator std::string () const return _string; case type_date: - return ISO8601d (_date).toISOLocalExtended (); + return Datetime (_date).toISOLocalExtended (); case type_duration: - return ISO8601p (_duration).format (); + return Duration (_duration).formatISO (); } return ""; @@ -1836,11 +1838,11 @@ void Variant::cast (const enum type new_type) } pos = 0; - ISO8601p isop; + Duration isop; if (isop.parse (_string, pos) && pos == _string.length ()) { - _date = ISO8601d ().toEpoch () + (time_t) isop; + _date = ISO8601d ().toEpoch () + isop.toTime_t (); break; } @@ -1855,11 +1857,11 @@ void Variant::cast (const enum type new_type) { _duration = 0; std::string::size_type pos = 0; - ISO8601p iso; + Duration iso; if (iso.parse (_string, pos) && pos == _string.length ()) { - _duration = (time_t) iso; + _duration = iso.toTime_t (); } } break; From 1c3a68edc047bfc5c7daa611211c1d8779a974fe Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 21:07:06 -0500 Subject: [PATCH 0166/1455] sort: Converted from ISO8601p to Duration --- src/sort.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sort.cpp b/src/sort.cpp index 055fc6f66..35c8194cc 100644 --- a/src/sort.cpp +++ b/src/sort.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -190,8 +190,8 @@ static bool sort_compare (int left, int right) if (left_string == right_string) continue; - ISO8601p left_duration (left_string); - ISO8601p right_duration (right_string); + Duration left_duration (left_string); + Duration right_duration (right_string); return ascending ? (left_duration < right_duration) : (left_duration > right_duration); } @@ -266,8 +266,8 @@ static bool sort_compare (int left, int right) if (left_string == right_string) continue; - ISO8601p left_duration (left_string); - ISO8601p right_duration (right_string); + Duration left_duration (left_string); + Duration right_duration (right_string); return ascending ? (left_duration < right_duration) : (left_duration > right_duration); } From 2d9c28f47e1326d72dc6929ac2dd2defb246d5b9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 21:13:07 -0500 Subject: [PATCH 0167/1455] Task: Converted from ISO8601p to Duration --- src/Task.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Task.cpp b/src/Task.cpp index e8b82905c..552bc2729 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -41,6 +41,7 @@ #include #include #endif +#include #include #ifdef PRODUCT_TASKWARRIOR #include @@ -1544,9 +1545,9 @@ void Task::validate (bool applyDefault /* = true */) { if (context.columns["due"]->validate (Task::defaultDue)) { - ISO8601p dur (Task::defaultDue); - if ((time_t) dur != 0) - set ("due", (ISO8601d () + dur).toEpoch ()); + Duration dur (Task::defaultDue); + if (dur.toTime_t () != 0) + set ("due", (ISO8601d () + dur.toTime_t ()).toEpoch ()); else set ("due", ISO8601d (Task::defaultDue).toEpoch ()); } @@ -1612,7 +1613,7 @@ void Task::validate (bool applyDefault /* = true */) std::string value = get ("recur"); if (value != "") { - ISO8601p p; + Duration p; std::string::size_type i = 0; if (! p.parse (value, i)) throw format (STRING_TASK_VALID_RECUR, value); From 8a3af0c4a6fed028415dbce387ec830863c15a54 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 21:32:41 -0500 Subject: [PATCH 0168/1455] recur: Converted from ISO8601p to Duration --- src/recur.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/recur.cpp b/src/recur.cpp index 9a09f9a12..d2800f244 100644 --- a/src/recur.cpp +++ b/src/recur.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -364,14 +365,12 @@ ISO8601d getNextRecurrence (ISO8601d& current, std::string& period) } // Add the period to current, and we're done. - int secs = 0; std::string::size_type idx = 0; - ISO8601p p; + Duration p; if (! p.parse (period, idx)) throw std::string (format (STRING_TASK_VALID_RECUR, period)); - secs = (time_t) p; - return current + secs; + return current + p.toTime_t (); } //////////////////////////////////////////////////////////////////////////////// From 3ef2459f2e739ae70e5b143e876ce08c2eeccfd2 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 21:39:27 -0500 Subject: [PATCH 0169/1455] feedback: Migrated from ISO8601 to Datetime/Duration --- src/feedback.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/feedback.cpp b/src/feedback.cpp index 3a96f473d..bbb9e057b 100644 --- a/src/feedback.cpp +++ b/src/feedback.cpp @@ -33,7 +33,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -183,7 +184,7 @@ std::string taskInfoDifferences ( else if (name == "start") { out << format (STRING_FEEDBACK_ATT_DEL_DUR, Lexer::ucFirst (name), - ISO8601p (current_timestamp - last_timestamp).format ()) + Duration (current_timestamp - last_timestamp).format ()) << "\n"; } else @@ -272,7 +273,7 @@ std::string renderAttribute (const std::string& name, const std::string& value, col->type () == "date" && value != "") { - ISO8601d d ((time_t)strtol (value.c_str (), NULL, 10)); + Datetime d ((time_t)strtol (value.c_str (), NULL, 10)); if (format == "") return d.toString (context.config.get ("dateformat")); From bc58b82e96988088e0ad67c770b04edd834f89e5 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 21:46:46 -0500 Subject: [PATCH 0170/1455] DOM: Converted from ISO8601 to Datetime/Duration - In addition fixed the week number of 2011-09-01 to 35, therefore the tests change also. --- src/DOM.cpp | 13 +++++++------ test/dom.t | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/DOM.cpp b/src/DOM.cpp index 74f063bbe..eba6b30aa 100644 --- a/src/DOM.cpp +++ b/src/DOM.cpp @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -261,12 +262,12 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) { auto period = ref.get (canonical); - ISO8601p iso; + Duration iso; std::string::size_type cursor = 0; if (iso.parse (period, cursor)) - value = Variant ((time_t) iso, Variant::type_duration); + value = Variant (iso.toTime_t (), Variant::type_duration); else - value = Variant ((time_t) ISO8601p (ref.get (canonical)), Variant::type_duration); + value = Variant (Duration (ref.get (canonical)).toTime_t (), Variant::type_duration); } else if (column->type () == "numeric") value = Variant (ref.get_float (canonical)); @@ -284,7 +285,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) if (ref.data.size () && size == 2 && column && column->type () == "date") { - ISO8601d date (ref.get_date (canonical)); + Datetime 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; } @@ -348,7 +349,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) // ..entry.hour // ..entry.minute // ..entry.second - ISO8601d date (i.first.substr (11)); + Datetime 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; } diff --git a/test/dom.t b/test/dom.t index d26032836..b741603f8 100755 --- a/test/dom.t +++ b/test/dom.t @@ -124,7 +124,7 @@ class TestDOM(TestCase): def test_dom_due_week(self): """ DOM 3.due.week """ code, out, err = self.t("_get 3.due.week") - self.assertEqual("36\n", out) + self.assertEqual("35\n", out) def test_dom_due_weekday(self): """ DOM 3.due.weekday """ From 5efca167484580aa45131f7c17b493730416787d Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 21:52:30 -0500 Subject: [PATCH 0171/1455] ColTypeDate: Converted fomr ISO8601 to Datetime/Duration --- src/columns/ColTypeDate.cpp | 57 +++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/columns/ColTypeDate.cpp b/src/columns/ColTypeDate.cpp index c996f3f4f..357c9d6ce 100644 --- a/src/columns/ColTypeDate.cpp +++ b/src/columns/ColTypeDate.cpp @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -54,16 +55,16 @@ ColumnTypeDate::ColumnTypeDate () "remaining", "countdown"}; - ISO8601d now; + Datetime now; now -= 125; // So that "age" is non-zero. _examples = {now.toString (context.config.get ("dateformat")), format (now.toJulian (), 13, 12), now.toEpochString (), now.toISO (), - ISO8601p (ISO8601d () - now).formatVague (), - '-' + ISO8601p (ISO8601d () - now).formatVague (), + Duration (Datetime () - now).formatVague (), + '-' + Duration (Datetime () - now).formatVague (), "", - ISO8601p (ISO8601d () - now).format ()}; + Duration (Datetime () - now).format ()}; } //////////////////////////////////////////////////////////////////////////////// @@ -74,7 +75,7 @@ void ColumnTypeDate::measure (Task& task, unsigned int& minimum, unsigned int& m if (task.has (_name)) { - ISO8601d date (task.get_date (_name)); + Datetime date (task.get_date (_name)); if (_style == "default" || _style == "formatted") @@ -89,12 +90,12 @@ void ColumnTypeDate::measure (Task& task, unsigned int& minimum, unsigned int& m if (format == "") format = context.config.get ("dateformat"); - minimum = maximum = ISO8601d::length (format); + minimum = maximum = Datetime::length (format); } else if (_style == "countdown") { - ISO8601d now; - minimum = maximum = ISO8601p (now - date).formatVague ().length (); + Datetime now; + minimum = maximum = Duration (now - date).formatVague ().length (); } else if (_style == "julian") { @@ -110,25 +111,25 @@ void ColumnTypeDate::measure (Task& task, unsigned int& minimum, unsigned int& m } else if (_style == "age") { - ISO8601d now; + Datetime now; if (now > date) - minimum = maximum = ISO8601p (now - date).formatVague ().length (); + minimum = maximum = Duration (now - date).formatVague ().length (); else - minimum = maximum = ISO8601p (date - now).formatVague ().length () + 1; + minimum = maximum = Duration (date - now).formatVague ().length () + 1; } else if (_style == "relative") { - ISO8601d now; + Datetime now; if (now < date) - minimum = maximum = ISO8601p (date - now).formatVague ().length (); + minimum = maximum = Duration (date - now).formatVague ().length (); else - minimum = maximum = ISO8601p (now - date).formatVague ().length () + 1; + minimum = maximum = Duration (now - date).formatVague ().length () + 1; } else if (_style == "remaining") { - ISO8601d now; + Datetime now; if (date > now) - minimum = maximum = ISO8601p (date - now).formatVague ().length (); + minimum = maximum = Duration (date - now).formatVague ().length (); } else throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); @@ -144,7 +145,7 @@ void ColumnTypeDate::render ( { if (task.has (_name)) { - ISO8601d date (task.get_date (_name)); + Datetime date (task.get_date (_name)); if (_style == "default" || _style == "formatted") @@ -165,8 +166,8 @@ void ColumnTypeDate::render ( } else if (_style == "countdown") { - ISO8601d now; - renderStringRight (lines, width, color, ISO8601p (now - date).formatVague ()); + Datetime now; + renderStringRight (lines, width, color, Duration (now - date).formatVague ()); } else if (_style == "julian") renderStringRight (lines, width, color, format (date.toJulian (), 13, 12)); @@ -179,26 +180,26 @@ void ColumnTypeDate::render ( else if (_style == "age") { - ISO8601d now; + Datetime now; if (now > date) - renderStringLeft (lines, width, color, ISO8601p (now - date).formatVague ()); + renderStringLeft (lines, width, color, Duration (now - date).formatVague ()); else - renderStringLeft (lines, width, color, '-' + ISO8601p (date - now).formatVague ()); + renderStringLeft (lines, width, color, '-' + Duration (date - now).formatVague ()); } else if (_style == "relative") { - ISO8601d now; + Datetime now; if (now < date) - renderStringLeft (lines, width, color, ISO8601p (date - now).formatVague ()); + renderStringLeft (lines, width, color, Duration (date - now).formatVague ()); else - renderStringLeft (lines, width, color, '-' + ISO8601p (now - date).formatVague ()); + renderStringLeft (lines, width, color, '-' + Duration (now - date).formatVague ()); } else if (_style == "remaining") { - ISO8601d now; + Datetime now; if (date > now) - renderStringRight (lines, width, color, ISO8601p (date - now).formatVague ()); + renderStringRight (lines, width, color, Duration (date - now).formatVague ()); } } } From cb82795d86f2a989b22dd72dcfd4fc66448040b0 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 22:06:47 -0500 Subject: [PATCH 0172/1455] CmdEdit: Converted from ISO8601 to Datetime/Duration --- src/commands/CmdEdit.cpp | 53 ++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/src/commands/CmdEdit.cpp b/src/commands/CmdEdit.cpp index a43e99bde..9e6b52e80 100644 --- a/src/commands/CmdEdit.cpp +++ b/src/commands/CmdEdit.cpp @@ -33,7 +33,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -174,10 +175,7 @@ std::string CmdEdit::formatDate ( { std::string value = task.get (attribute); if (value.length ()) - { - ISO8601d dt (value); - value = dt.toString (dateformat); - } + value = Datetime (value).toString (dateformat); return value; } @@ -189,10 +187,7 @@ std::string CmdEdit::formatDuration ( { std::string value = task.get (attribute); if (value.length ()) - { - ISO8601p dur (value); - value = dur.format (); - } + value = Duration (value).formatISO (); return value; } @@ -258,12 +253,12 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) task.getAnnotations (annotations); for (auto& anno : annotations) { - ISO8601d dt (strtol (anno.first.substr (11).c_str (), NULL, 10)); + Datetime dt (strtol (anno.first.substr (11).c_str (), NULL, 10)); before << " Annotation: " << dt.toString (dateformat) << " -- " << json::encode (anno.second) << '\n'; } - ISO8601d now; + Datetime now; before << " Annotation: " << now.toString (dateformat) << " -- \n"; // Add dependencies here. @@ -386,7 +381,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string if (formatted != value) { context.footnote (STRING_EDIT_ENTRY_MOD); - task.set ("entry", ISO8601d (value, dateformat).toEpochString ()); + task.set ("entry", Datetime (value, dateformat).toEpochString ()); } } else @@ -403,13 +398,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string if (formatted != value) { context.footnote (STRING_EDIT_START_MOD); - task.set ("start", ISO8601d (value, dateformat).toEpochString ()); + task.set ("start", Datetime (value, dateformat).toEpochString ()); } } else { context.footnote (STRING_EDIT_START_MOD); - task.set ("start", ISO8601d (value, dateformat).toEpochString ()); + task.set ("start", Datetime (value, dateformat).toEpochString ()); } } else @@ -432,7 +427,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string if (formatted != value) { context.footnote (STRING_EDIT_END_MOD); - task.set ("end", ISO8601d (value, dateformat).toEpochString ()); + task.set ("end", Datetime (value, dateformat).toEpochString ()); } } else if (task.getStatus () != Task::deleted) @@ -459,13 +454,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string if (formatted != value) { context.footnote (STRING_EDIT_SCHED_MOD); - task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ()); + task.set ("scheduled", Datetime (value, dateformat).toEpochString ()); } } else { context.footnote (STRING_EDIT_SCHED_MOD); - task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ()); + task.set ("scheduled", Datetime (value, dateformat).toEpochString ()); } } else @@ -489,13 +484,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string if (formatted != value) { context.footnote (STRING_EDIT_DUE_MOD); - task.set ("due", ISO8601d (value, dateformat).toEpochString ()); + task.set ("due", Datetime (value, dateformat).toEpochString ()); } } else { context.footnote (STRING_EDIT_DUE_MOD); - task.set ("due", ISO8601d (value, dateformat).toEpochString ()); + task.set ("due", Datetime (value, dateformat).toEpochString ()); } } else @@ -526,13 +521,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string if (formatted != value) { context.footnote (STRING_EDIT_UNTIL_MOD); - task.set ("until", ISO8601d (value, dateformat).toEpochString ()); + task.set ("until", Datetime (value, dateformat).toEpochString ()); } } else { context.footnote (STRING_EDIT_UNTIL_MOD); - task.set ("until", ISO8601d (value, dateformat).toEpochString ()); + task.set ("until", Datetime (value, dateformat).toEpochString ()); } } else @@ -550,7 +545,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != "") { - ISO8601p p; + Duration p; std::string::size_type idx = 0; if (p.parse (value, idx)) { @@ -588,14 +583,14 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string if (formatted != value) { context.footnote (STRING_EDIT_WAIT_MOD); - task.set ("wait", ISO8601d (value, dateformat).toEpochString ()); + task.set ("wait", Datetime (value, dateformat).toEpochString ()); task.setStatus (Task::waiting); } } else { context.footnote (STRING_EDIT_WAIT_MOD); - task.set ("wait", ISO8601d (value, dateformat).toEpochString ()); + task.set ("wait", Datetime (value, dateformat).toEpochString ()); task.setStatus (Task::waiting); } } @@ -649,7 +644,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string // 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). - ISO8601d when (value.substr (0, gap), dateformat); + Datetime when (value.substr (0, gap), dateformat); // If the map already contains a annotation for a given timestamp // we need to increment until we find an unused key @@ -694,9 +689,9 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { 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 ())) && + (task.get (col.first) != Datetime (value, dateformat).toEpochString ())) && (type != "duration" || - (task.get (col.first) != (std::string) ISO8601p (value)))) + (task.get (col.first) != Duration (value).toString ()))) { if (value != "") { @@ -718,11 +713,11 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string } else if (type == "date") { - task.set (col.first, ISO8601d (value, dateformat).toEpochString ()); + task.set (col.first, Datetime (value, dateformat).toEpochString ()); } else if (type == "duration") { - task.set (col.first, (time_t) ISO8601p (value)); + task.set (col.first, Duration (value).toTime_t ()); } } else From 4c2fff1b39d11fb612be60c7320e5db19fd8dcdb Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 22:21:06 -0500 Subject: [PATCH 0173/1455] ColRecur: Converted from ISO8601 to Duration --- src/columns/ColRecur.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/columns/ColRecur.cpp b/src/columns/ColRecur.cpp index aa1c85397..129c0e4ac 100644 --- a/src/columns/ColRecur.cpp +++ b/src/columns/ColRecur.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -73,7 +73,7 @@ void ColumnRecur::measure (Task& task, unsigned int& minimum, unsigned int& maxi if (_style == "default" || _style == "duration") { - minimum = maximum = ISO8601p (task.get ("recur")).format ().length (); + minimum = maximum = Duration (task.get ("recur")).formatISO ().length (); } else if (_style == "indicator") { @@ -98,7 +98,7 @@ void ColumnRecur::render ( { if (_style == "default" || _style == "duration") - renderStringRight (lines, width, color, ISO8601p (task.get ("recur")).format ()); + renderStringRight (lines, width, color, Duration (task.get ("recur")).formatISO ()); else if (_style == "indicator") renderStringRight (lines, width, color, context.config.get ("recurrence.indicator")); From c8bdfab4b416bd27e7b7c2d24925c7b0ee3b7ab3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 22:23:53 -0500 Subject: [PATCH 0174/1455] ColUDA: Converted from ISO8601 to Datetime/Duration --- src/columns/ColUDA.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/columns/ColUDA.cpp b/src/columns/ColUDA.cpp index d2f316a3c..b59e4c562 100644 --- a/src/columns/ColUDA.cpp +++ b/src/columns/ColUDA.cpp @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -265,14 +266,14 @@ void ColumnUDADate::measure (Task& task, unsigned int& minimum, unsigned int& ma // rc.report..dateformat // rc.dateformat.report // rc.dateformat - ISO8601d date ((time_t) strtol (value.c_str (), NULL, 10)); + Datetime 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 = ISO8601d::length (format); + minimum = maximum = Datetime::length (format); } } else if (_style == "indicator") @@ -318,7 +319,7 @@ void ColumnUDADate::render ( format = context.config.get ("dateformat"); } - renderStringLeft (lines, width, color, ISO8601d ((time_t) strtol (value.c_str (), NULL, 10)).toString (format)); + renderStringLeft (lines, width, color, Datetime ((time_t) strtol (value.c_str (), NULL, 10)).toString (format)); } else if (_style == "indicator") { @@ -374,7 +375,7 @@ void ColumnUDADuration::measure (Task& task, unsigned int& minimum, unsigned int { std::string value = task.get (_name); if (value != "") - minimum = maximum = ISO8601p (value).format ().length (); + minimum = maximum = Duration (value).formatISO ().length (); } else if (_style == "indicator") { @@ -406,7 +407,7 @@ void ColumnUDADuration::render ( if (_style == "default") { std::string value = task.get (_name); - renderStringRight (lines, width, color, ISO8601p (value).format ()); + renderStringRight (lines, width, color, Duration (value).formatISO ()); } else if (_style == "indicator") { From 72076abc74d13ab325190539d0be3913db4a3390 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 22:27:18 -0500 Subject: [PATCH 0175/1455] CmdInfo: Converted from ISO8601 to Datetime/Duration --- src/commands/CmdInfo.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index 9aa8b9b6c..7b87870ae 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -31,7 +31,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -114,7 +115,7 @@ int CmdInfo::execute (std::string& output) view.colorHeader (label); } - ISO8601d now; + Datetime now; // id int row = view.addRow (); @@ -134,7 +135,7 @@ int CmdInfo::execute (std::string& output) for (auto& anno : annotations) description += '\n' + std::string (indent, ' ') - + ISO8601d (anno.first.substr (11)).toString (dateformatanno) + + Datetime (anno.first.substr (11)).toString (dateformatanno) + ' ' + anno.second; @@ -222,15 +223,15 @@ int CmdInfo::execute (std::string& output) // entry row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_ENTERED); - ISO8601d dt (task.get_date ("entry")); + Datetime dt (task.get_date ("entry")); std::string entry = dt.toString (dateformat); std::string age; std::string created = task.get ("entry"); if (created.length ()) { - ISO8601d dt (strtol (created.c_str (), NULL, 10)); - age = ISO8601p (now - dt).formatVague (); + Datetime dt (strtol (created.c_str (), NULL, 10)); + age = Duration (now - dt).formatVague (); } view.set (row, 1, entry + " (" + age + ')'); @@ -240,7 +241,7 @@ int CmdInfo::execute (std::string& output) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_WAITING); - view.set (row, 1, ISO8601d (task.get_date ("wait")).toString (dateformat)); + view.set (row, 1, Datetime (task.get_date ("wait")).toString (dateformat)); } // scheduled @@ -248,7 +249,7 @@ int CmdInfo::execute (std::string& output) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_SCHED); - view.set (row, 1, ISO8601d (task.get_date ("scheduled")).toString (dateformat)); + view.set (row, 1, Datetime (task.get_date ("scheduled")).toString (dateformat)); } // start @@ -256,7 +257,7 @@ int CmdInfo::execute (std::string& output) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_START); - view.set (row, 1, ISO8601d (task.get_date ("start")).toString (dateformat)); + view.set (row, 1, Datetime (task.get_date ("start")).toString (dateformat)); } // due (colored) @@ -264,7 +265,7 @@ int CmdInfo::execute (std::string& output) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_DUE); - view.set (row, 1, ISO8601d (task.get_date ("due")).toString (dateformat)); + view.set (row, 1, Datetime (task.get_date ("due")).toString (dateformat)); } // end @@ -272,7 +273,7 @@ int CmdInfo::execute (std::string& output) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_END); - view.set (row, 1, ISO8601d (task.get_date ("end")).toString (dateformat)); + view.set (row, 1, Datetime (task.get_date ("end")).toString (dateformat)); } // until @@ -280,7 +281,7 @@ int CmdInfo::execute (std::string& output) { row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_UNTIL); - view.set (row, 1, ISO8601d (task.get_date ("until")).toString (dateformat)); + view.set (row, 1, Datetime (task.get_date ("until")).toString (dateformat)); } // modified @@ -289,8 +290,8 @@ int CmdInfo::execute (std::string& output) row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_MODIFIED); - ISO8601d mod (task.get_date ("modified")); - std::string age = ISO8601p (now - mod).formatVague (); + Datetime mod (task.get_date ("modified")); + std::string age = Duration (now - mod).formatVague (); view.set (row, 1, mod.toString (dateformat) + " (" + age + ')'); } @@ -375,13 +376,13 @@ int CmdInfo::execute (std::string& output) view.set (row, 0, col->label ()); if (type == "date") - value = ISO8601d (value).toString (dateformat); + value = Datetime (value).toString (dateformat); else if (type == "duration") { - ISO8601p iso; + Duration iso; std::string::size_type cursor = 0; if (iso.parse (value, cursor)) - value = (std::string) Variant ((time_t) iso, Variant::type_duration); + value = (std::string) Variant (iso.toTime_t (), Variant::type_duration); else value = "PT0S"; } @@ -546,7 +547,7 @@ int CmdInfo::execute (std::string& output) { int row = journal.addRow (); - ISO8601d timestamp (strtol (undo[when].substr (5).c_str (), NULL, 10)); + Datetime timestamp (strtol (undo[when].substr (5).c_str (), NULL, 10)); journal.set (row, 0, timestamp.toString (dateformat)); Task before (undo[previous].substr (4)); From 61b4e36b2cbab6b9fffb8c433d5f0e9f8ed779b8 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 23:13:27 -0500 Subject: [PATCH 0176/1455] CmdBurndown: Converted from ISO8601 to Duration --- src/commands/CmdBurndown.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/commands/CmdBurndown.cpp b/src/commands/CmdBurndown.cpp index ad43dd664..0bfd94475 100644 --- a/src/commands/CmdBurndown.cpp +++ b/src/commands/CmdBurndown.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -838,14 +839,14 @@ void Chart::calculateRates () rate_message << "Chart::calculateRates Net reduction is " << (_peak_count - _current_count) << " tasks in " - << ISO8601p (now.toEpoch () - _peak_epoch).format () + << Duration (now.toEpoch () - _peak_epoch).formatISO () << " = " << _net_fix_rate << " tasks/d"; context.debug (rate_message.str ()); - ISO8601p delta (static_cast (_current_count / fix_rate)); - ISO8601d end = now + delta; + Duration delta (static_cast (_current_count / fix_rate)); + ISO8601d end = now + delta.toTime_t (); // Prefer dateformat.report over dateformat. std::string format = context.config.get ("dateformat.report"); From bbce4da1c90803850d4b7960e439034837a4ff37 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 23:48:39 -0500 Subject: [PATCH 0177/1455] CmdSummary: Converted from ISO8601 to Duration --- src/commands/CmdSummary.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index 85272c11a..f18d41278 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -175,7 +175,7 @@ int CmdSummary::execute (std::string& output) 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 ()); + view.set (row, 2, Duration ((int) (sumEntry[i.first] / (double)counter[i.first])).formatVague ()); int c = countCompleted[i.first]; int p = countPending[i.first]; From b51e8a294524a978cda565178b644d34b1bf04ef Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 11 Dec 2016 23:52:18 -0500 Subject: [PATCH 0178/1455] CmdStats: Converted from ISO8601 to Datetime/Duration --- src/commands/CmdStats.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/commands/CmdStats.cpp b/src/commands/CmdStats.cpp index 5d2df249a..eab173f39 100644 --- a/src/commands/CmdStats.cpp +++ b/src/commands/CmdStats.cpp @@ -30,7 +30,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -90,7 +91,7 @@ int CmdStats::execute (std::string& output) std::vector filtered; filter.subset (all, filtered); - ISO8601d now; + Datetime now; time_t earliest = time (NULL); time_t latest = 1; int totalT = 0; @@ -238,47 +239,47 @@ int CmdStats::execute (std::string& output) if (filtered.size ()) { - ISO8601d e (earliest); + Datetime e (earliest); row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_OLDEST); view.set (row, 1, e.toString (dateformat)); - ISO8601d l (latest); + Datetime 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, ISO8601p (latest - earliest).formatVague ()); + view.set (row, 1, Duration (latest - earliest).formatVague ()); } if (totalT) { row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_ADD_EVERY); - view.set (row, 1, ISO8601p (((latest - earliest) / totalT)).formatVague ()); + view.set (row, 1, Duration (((latest - earliest) / totalT)).formatVague ()); } if (completedT) { row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_COMP_EVERY); - view.set (row, 1, ISO8601p ((latest - earliest) / completedT).formatVague ()); + view.set (row, 1, Duration ((latest - earliest) / completedT).formatVague ()); } if (deletedT) { row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_DEL_EVERY); - view.set (row, 1, ISO8601p ((latest - earliest) / deletedT).formatVague ()); + view.set (row, 1, Duration ((latest - earliest) / deletedT).formatVague ()); } if (pendingT || completedT) { row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_AVG_PEND); - view.set (row, 1, ISO8601p ((int) ((daysPending / (pendingT + completedT)) * 86400)).formatVague ()); + view.set (row, 1, Duration ((int) ((daysPending / (pendingT + completedT)) * 86400)).formatVague ()); } if (totalT) From 5b7fca8c639ffded09ad25126d0640c3752bdeee Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 12 Dec 2016 08:28:06 -0500 Subject: [PATCH 0179/1455] Context: Removed unused class global --- src/Context.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Context.cpp b/src/Context.cpp index b4292ca7f..d330cfda3 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -689,7 +690,7 @@ void Context::staticInitialization () Task::searchCaseSensitive = Variant::searchCaseSensitive = config.getBoolean ("search.case.sensitive"); Task::regex = Variant::searchUsingRegex = config.getBoolean ("regex"); Lexer::dateFormat = Variant::dateFormat = config.get ("dateformat"); - ISO8601p::isoEnabled = ISO8601d::isoEnabled = config.getBoolean ("date.iso"); + Datetime::isoEnabled = ISO8601d::isoEnabled = config.getBoolean ("date.iso"); TDB2::debug_mode = config.getBoolean ("debug"); From c77487994e852bb65f913e02c1d6f9b38b3ea661 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 12 Dec 2016 08:28:24 -0500 Subject: [PATCH 0180/1455] util: Added missing include --- src/util.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util.cpp b/src/util.cpp index bd330eceb..1752b39c1 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -54,6 +54,7 @@ #include #include +#include #include #include From 3e45b9cf1e7ed88985c595ada0f0d246cd862502 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 12:59:05 -0500 Subject: [PATCH 0181/1455] L10N: Removed unused strings --- src/l10n/deu-DEU.h | 18 ------------------ src/l10n/eng-USA.h | 18 ------------------ src/l10n/epo-RUS.h | 18 ------------------ src/l10n/esp-ESP.h | 18 ------------------ src/l10n/fra-FRA.h | 18 ------------------ src/l10n/ita-ITA.h | 18 ------------------ src/l10n/jpn-JPN.h | 18 ------------------ src/l10n/pol-POL.h | 18 ------------------ src/l10n/por-PRT.h | 18 ------------------ 9 files changed, 162 deletions(-) diff --git a/src/l10n/deu-DEU.h b/src/l10n/deu-DEU.h index 8e7496067..aae7aea89 100644 --- a/src/l10n/deu-DEU.h +++ b/src/l10n/deu-DEU.h @@ -795,10 +795,6 @@ #define STRING_FEEDBACK_EXPIRED "Aufgabe {1} '{2}' ist abgelaufen und wurde gelöscht." #define STRING_FEEDBACK_BACKLOG "Lokale Änderungen. Datenabgleich erforderlich." -// File -#define STRING_FILE_PERMS "Taskwarrior hat die erforderlichen Rechte auf '{1}' nicht." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." #define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete" @@ -817,15 +813,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script." -// JSON -#define STRING_JSON_MISSING_VALUE "Fehler: Fehlender Wert nach ',' an Position {1}" -#define STRING_JSON_MISSING_VALUE2 "Fehler: Fehlender Wert an Position {1}" -#define STRING_JSON_MISSING_BRACKET "Fehler: Fehlendes ']' an Position {1}" -#define STRING_JSON_MISSING_BRACE "Fehler: Fehlendes '}' an Position {1}" -#define STRING_JSON_MISSING_COLON "Fehler: Fehlendes ':' an Position {1}" -#define STRING_JSON_MISSING_OPEN "Fehler: '{' oder '[' an Position {1} erwartet" -#define STRING_JSON_EXTRA_CHARACTERS "Fehler: Überschüssige Zeichen an position {1} gefunden" - // Record #define STRING_RECORD_EMPTY "Leerer Datensatz in der Eingabe." #define STRING_RECORD_JUNK_AT_EOL "Unerkannte Zeichen am Ende der Eingabe." @@ -1014,17 +1001,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (ja/nein) " #define STRING_UTIL_CONFIRM_YES "ja" #define STRING_UTIL_CONFIRM_YES_U "Ja" #define STRING_UTIL_CONFIRM_NO "nein" #define STRING_UTIL_CONFIRM_ALL "alle" #define STRING_UTIL_CONFIRM_ALL_U "Alle" #define STRING_UTIL_CONFIRM_QUIT "abbrechen" -#define STRING_UTIL_GIBIBYTES "GiB" -#define STRING_UTIL_MEBIBYTES "MiB" -#define STRING_UTIL_KIBIBYTES "KiB" -#define STRING_UTIL_BYTES "B" // Legacy #define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'." diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 75916f5f1..c0e477f1a 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -793,10 +793,6 @@ #define STRING_FEEDBACK_EXPIRED "Task {1} '{2}' expired and was deleted." #define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required." -// File -#define STRING_FILE_PERMS "Taskwarrior does not have the correct permissions for '{1}'." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." #define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete" @@ -815,15 +811,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script." -// JSON -#define STRING_JSON_MISSING_VALUE "Error: missing value after ',' at position {1}" -#define STRING_JSON_MISSING_VALUE2 "Error: missing value at position {1}" -#define STRING_JSON_MISSING_BRACKET "Error: missing ']' at position {1}" -#define STRING_JSON_MISSING_BRACE "Error: missing '}' at position {1}" -#define STRING_JSON_MISSING_COLON "Error: missing ':' at position {1}" -#define STRING_JSON_MISSING_OPEN "Error: expected '{' or '[' at position {1}" -#define STRING_JSON_EXTRA_CHARACTERS "Error: extra characters found at position {1}" - // Record #define STRING_RECORD_EMPTY "Empty record in input." #define STRING_RECORD_JUNK_AT_EOL "Unrecognized characters at end of line." @@ -1009,17 +996,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (yes/no) " #define STRING_UTIL_CONFIRM_YES "yes" #define STRING_UTIL_CONFIRM_YES_U "Yes" #define STRING_UTIL_CONFIRM_NO "no" #define STRING_UTIL_CONFIRM_ALL "all" #define STRING_UTIL_CONFIRM_ALL_U "All" #define STRING_UTIL_CONFIRM_QUIT "quit" -#define STRING_UTIL_GIBIBYTES "GiB" -#define STRING_UTIL_MEBIBYTES "MiB" -#define STRING_UTIL_KIBIBYTES "KiB" -#define STRING_UTIL_BYTES "B" // Legacy #define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'." diff --git a/src/l10n/epo-RUS.h b/src/l10n/epo-RUS.h index 0c02e4caa..fd6fa3785 100644 --- a/src/l10n/epo-RUS.h +++ b/src/l10n/epo-RUS.h @@ -795,10 +795,6 @@ #define STRING_FEEDBACK_EXPIRED "Tasko {1} '{2}' fortempiĝis do estis viŝata." #define STRING_FEEDBACK_BACKLOG "Estas lokaj ŝanĝoj. Sinkronigo devita." -// File -#define STRING_FILE_PERMS "Taskwarrior ne havas la bezonatan permeson por '{1}'." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." #define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete" @@ -817,15 +813,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script." -// JSON -#define STRING_JSON_MISSING_VALUE "Eraro: mankas valoro post ',' ĉe pozicio {1}" -#define STRING_JSON_MISSING_VALUE2 "Eraro: mankas valoro ĉe pozicio {1}" -#define STRING_JSON_MISSING_BRACKET "Eraro: mankas ']' ĉe pozicio {1}" -#define STRING_JSON_MISSING_BRACE "Eraro: mankas '}' ĉe pozicio {1}" -#define STRING_JSON_MISSING_COLON "Eraro: mankas ':' ĉe pozicio {1}" -#define STRING_JSON_MISSING_OPEN "Eraro: anticipis '{' aŭ '[' ĉe pozicio {1}" -#define STRING_JSON_EXTRA_CHARACTERS "Eraro: trovis pliajn signojn ĉe pozicio {1}" - // Record #define STRING_RECORD_EMPTY "Malplena rikordo en la inigo." #define STRING_RECORD_JUNK_AT_EOL "Nekonataj signoj ĉe vicfino." @@ -1011,17 +998,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (jes/ne) " #define STRING_UTIL_CONFIRM_YES "jes" #define STRING_UTIL_CONFIRM_YES_U "Jes" #define STRING_UTIL_CONFIRM_NO "ne" #define STRING_UTIL_CONFIRM_ALL "ĉia" #define STRING_UTIL_CONFIRM_ALL_U "Ĉia" #define STRING_UTIL_CONFIRM_QUIT "eliru" -#define STRING_UTIL_GIBIBYTES "GiB" -#define STRING_UTIL_MEBIBYTES "MiB" -#define STRING_UTIL_KIBIBYTES "KiB" -#define STRING_UTIL_BYTES "B" // Legacy #define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'." diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index e48f429ce..1e612e9b5 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -804,10 +804,6 @@ #define STRING_FEEDBACK_EXPIRED "La tarea {1} '{2}' caducó y fue eliminada." #define STRING_FEEDBACK_BACKLOG "Hay modificaciones locales. Se require una sincronización." -// File -#define STRING_FILE_PERMS "Taskwarrior no tiene los permisos adecuados para '{1}'." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "El proyecto '{1}' ha cambiado." #define STRING_HELPER_PROJECT_COMPL "El proyecto '{1}' está completado en un {2}%" @@ -826,15 +822,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON debe ser para la misma tarea: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: se esperaba retro-alimentación desde un hook script que falló." -// JSON -#define STRING_JSON_MISSING_VALUE "Error: falta valor después de ',' en posición {1}" -#define STRING_JSON_MISSING_VALUE2 "Error: falta valor en posición {1}" -#define STRING_JSON_MISSING_BRACKET "Error: falta ']' en posición {1}" -#define STRING_JSON_MISSING_BRACE "Error: falta '}' en posición {1}" -#define STRING_JSON_MISSING_COLON "Error: falta ':' en posición {1}" -#define STRING_JSON_MISSING_OPEN "Error: se esperaba '{' or '[' en posición {1}" -#define STRING_JSON_EXTRA_CHARACTERS "Error: encontrados caracteres extra en posición {1}" - // Record #define STRING_RECORD_EMPTY "Registro vacío en la entrada." #define STRING_RECORD_JUNK_AT_EOL "Caracteres no reconocidos al final de línea." @@ -1036,17 +1023,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (sí/no) " #define STRING_UTIL_CONFIRM_YES "sí" #define STRING_UTIL_CONFIRM_YES_U "Sí" #define STRING_UTIL_CONFIRM_NO "no" // |esp-ESP|==|eng-USA| #define STRING_UTIL_CONFIRM_ALL "todos" #define STRING_UTIL_CONFIRM_ALL_U "Todos" #define STRING_UTIL_CONFIRM_QUIT "canc" -#define STRING_UTIL_GIBIBYTES "GiB" // |esp-ESP|==|eng-USA| -#define STRING_UTIL_MEBIBYTES "MiB" // |esp-ESP|==|eng-USA| -#define STRING_UTIL_KIBIBYTES "KiB" // |esp-ESP|==|eng-USA| -#define STRING_UTIL_BYTES "B" // |esp-ESP|==|eng-USA| // Legacy #define STRING_LEGACY_PRIORITY "Encontrado atributo anticuado. Por favor, cambie '{1}' a '{2}'." diff --git a/src/l10n/fra-FRA.h b/src/l10n/fra-FRA.h index ac468a930..2ca31651e 100644 --- a/src/l10n/fra-FRA.h +++ b/src/l10n/fra-FRA.h @@ -795,10 +795,6 @@ #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." -// File -#define STRING_FILE_PERMS "Taskwarrior does not have the correct permissions for '{1}'." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." #define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete" @@ -817,15 +813,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script." -// JSON -#define STRING_JSON_MISSING_VALUE "Erreur : valeur manquante après ',' à la position {1}" -#define STRING_JSON_MISSING_VALUE2 "Erreur : valeur manquante à la position {1}" -#define STRING_JSON_MISSING_BRACKET "Erreur : il manque ']' à la position {1}" -#define STRING_JSON_MISSING_BRACE "Erreur : il manque '}' à la position {1}" -#define STRING_JSON_MISSING_COLON "Erreur : il manque ':' à la position {1}" -#define STRING_JSON_MISSING_OPEN "Erreur : '{' or '[' attendu à la position {1}" -#define STRING_JSON_EXTRA_CHARACTERS "Erreur : caractères superflus à la position {1}" - // Record #define STRING_RECORD_EMPTY "Empty record in input." #define STRING_RECORD_JUNK_AT_EOL "Unrecognized characters at end of line." @@ -1011,17 +998,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (oui/non) " #define STRING_UTIL_CONFIRM_YES "oui" #define STRING_UTIL_CONFIRM_YES_U "Oui" #define STRING_UTIL_CONFIRM_NO "non" #define STRING_UTIL_CONFIRM_ALL "tous" #define STRING_UTIL_CONFIRM_ALL_U "Tous" #define STRING_UTIL_CONFIRM_QUIT "quitter" -#define STRING_UTIL_GIBIBYTES "Gio" -#define STRING_UTIL_MEBIBYTES "Mio" -#define STRING_UTIL_KIBIBYTES "kio" -#define STRING_UTIL_BYTES "o" // Legacy #define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'." diff --git a/src/l10n/ita-ITA.h b/src/l10n/ita-ITA.h index eaff151c9..768d14001 100644 --- a/src/l10n/ita-ITA.h +++ b/src/l10n/ita-ITA.h @@ -794,10 +794,6 @@ #define STRING_FEEDBACK_EXPIRED "Il task {1} '{2}' è scaduto ed è stato eliminato" #define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required." -// File -#define STRING_FILE_PERMS "Taskwarrior non dispone dei permessi corretti per '{1}'." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "Il progetto '{1}' è stato modificat." #define STRING_HELPER_PROJECT_COMPL "Il progetto '{1}' è {2}% completo" @@ -816,15 +812,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script." -// JSON -#define STRING_JSON_MISSING_VALUE "Errore: mancato valore dopo ',' alla posizione {1}" -#define STRING_JSON_MISSING_VALUE2 "Errore: mancato valore alla posizione {1}" -#define STRING_JSON_MISSING_BRACKET "Errore: mancato ']' alla posizione {1}" -#define STRING_JSON_MISSING_BRACE "Errore: mancato '}' alla posizione {1}" -#define STRING_JSON_MISSING_COLON "Errore: mancato ':' alla posizione {1}" -#define STRING_JSON_MISSING_OPEN "Errore: atteso '{' o '[' alla posizione {1}" -#define STRING_JSON_EXTRA_CHARACTERS "Errore: caratteri in eccesso alla posizione {1}" - // Record #define STRING_RECORD_EMPTY "Voce vuota in ingresso." #define STRING_RECORD_JUNK_AT_EOL "Carattere non riconosciuto a fine riga." @@ -1010,17 +997,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (si/no) " #define STRING_UTIL_CONFIRM_YES "si" #define STRING_UTIL_CONFIRM_YES_U "Si" #define STRING_UTIL_CONFIRM_NO "no" #define STRING_UTIL_CONFIRM_ALL "tutti" #define STRING_UTIL_CONFIRM_ALL_U "Tutti" #define STRING_UTIL_CONFIRM_QUIT "esci" -#define STRING_UTIL_GIBIBYTES "Gb" -#define STRING_UTIL_MEBIBYTES "Mb" -#define STRING_UTIL_KIBIBYTES "Kb" -#define STRING_UTIL_BYTES "B" // Legacy #define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'." diff --git a/src/l10n/jpn-JPN.h b/src/l10n/jpn-JPN.h index 14560d743..42a41b724 100644 --- a/src/l10n/jpn-JPN.h +++ b/src/l10n/jpn-JPN.h @@ -795,10 +795,6 @@ #define STRING_FEEDBACK_EXPIRED "Task {1} '{2}' expired and was deleted." #define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required." -// File -#define STRING_FILE_PERMS "Taskwarrior does not have the correct permissions for '{1}'." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." #define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete" @@ -817,15 +813,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script." -// JSON -#define STRING_JSON_MISSING_VALUE "Error: missing value after ',' at position {1}" -#define STRING_JSON_MISSING_VALUE2 "Error: missing value at position {1}" -#define STRING_JSON_MISSING_BRACKET "Error: missing ']' at position {1}" -#define STRING_JSON_MISSING_BRACE "Error: missing '}' at position {1}" -#define STRING_JSON_MISSING_COLON "Error: missing ':' at position {1}" -#define STRING_JSON_MISSING_OPEN "Error: expected '{' or '[' at position {1}" -#define STRING_JSON_EXTRA_CHARACTERS "Error: extra characters found at position {1}" - // Record #define STRING_RECORD_EMPTY "Empty record in input." #define STRING_RECORD_JUNK_AT_EOL "Unrecognized characters at end of line." @@ -1011,17 +998,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (yes/no) " #define STRING_UTIL_CONFIRM_YES "yes" #define STRING_UTIL_CONFIRM_YES_U "Yes" #define STRING_UTIL_CONFIRM_NO "no" #define STRING_UTIL_CONFIRM_ALL "all" #define STRING_UTIL_CONFIRM_ALL_U "All" #define STRING_UTIL_CONFIRM_QUIT "quit" -#define STRING_UTIL_GIBIBYTES "GiB" -#define STRING_UTIL_MEBIBYTES "MiB" -#define STRING_UTIL_KIBIBYTES "KiB" -#define STRING_UTIL_BYTES "B" // Legacy #define STRING_LEGACY_PRIORITY "古い属性が見つかった。'{1}' を '{2}' に変更してください。" diff --git a/src/l10n/pol-POL.h b/src/l10n/pol-POL.h index 382dd8528..d3ddabdb3 100644 --- a/src/l10n/pol-POL.h +++ b/src/l10n/pol-POL.h @@ -795,10 +795,6 @@ #define STRING_FEEDBACK_EXPIRED "Zadanie {1} '{2}' jest przedawnione i zostało usunięte." #define STRING_FEEDBACK_BACKLOG "Wykryto lokalne zmiany. Wymagana synchronizacja." -// File -#define STRING_FILE_PERMS "Taskwarrior nie posiada praw dostępu do '{1}'." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." #define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete" @@ -817,15 +813,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script." -// JSON -#define STRING_JSON_MISSING_VALUE "Błąd: brak wartości po ',' na pozycji {1}" -#define STRING_JSON_MISSING_VALUE2 "Błąd: brak wartości na pozycji {1}" -#define STRING_JSON_MISSING_BRACKET "Błąd: brak ']' na pozycji {1}" -#define STRING_JSON_MISSING_BRACE "Błąd: brak '}' na pozycji {1}" -#define STRING_JSON_MISSING_COLON "Błąd: brak ':' na pozycji {1}" -#define STRING_JSON_MISSING_OPEN "Błąd: oczekiwany '{' lub '[' na pozycji {1}" -#define STRING_JSON_EXTRA_CHARACTERS "Błąd: nadmiarowy znak na pozycji {1}" - // Record #define STRING_RECORD_EMPTY "Pusty wpis na wejściu." #define STRING_RECORD_JUNK_AT_EOL "Nierozpoznawalny znak na koncu lini." @@ -1011,17 +998,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (tak/nie) " #define STRING_UTIL_CONFIRM_YES "tak" #define STRING_UTIL_CONFIRM_YES_U "Tak" #define STRING_UTIL_CONFIRM_NO "nie" #define STRING_UTIL_CONFIRM_ALL "wszystko" #define STRING_UTIL_CONFIRM_ALL_U "Wszystko" #define STRING_UTIL_CONFIRM_QUIT "wyjście" -#define STRING_UTIL_GIBIBYTES "GiB" -#define STRING_UTIL_MEBIBYTES "MiB" -#define STRING_UTIL_KIBIBYTES "KiB" -#define STRING_UTIL_BYTES "B" // Legacy #define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'." diff --git a/src/l10n/por-PRT.h b/src/l10n/por-PRT.h index d11655965..f710f3f81 100644 --- a/src/l10n/por-PRT.h +++ b/src/l10n/por-PRT.h @@ -795,10 +795,6 @@ #define STRING_FEEDBACK_EXPIRED "Tarefa {1} '{2}' expirou e foi eliminada." #define STRING_FEEDBACK_BACKLOG "Há modificações locais. Necessário sincronizar (sync)." -// File -#define STRING_FILE_PERMS "O taskwarrior não encontrou as permissões corretas em '{1}'." -#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" - // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." #define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete" @@ -817,15 +813,6 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script." -// JSON -#define STRING_JSON_MISSING_VALUE "Erro: valor em falta após ',' na posição {1}" -#define STRING_JSON_MISSING_VALUE2 "Erro: valor em falta na posição {1}" -#define STRING_JSON_MISSING_BRACKET "Erro: ']' em falta na posição {1}" -#define STRING_JSON_MISSING_BRACE "Erro: '}' em falta na posição {1}" -#define STRING_JSON_MISSING_COLON "Erro: ':' em falta na posição {1}" -#define STRING_JSON_MISSING_OPEN "Erro: esperado '{' ou '[' na posição {1}" -#define STRING_JSON_EXTRA_CHARACTERS "Erro: caracteres extra encontrados na posição {1}" - // Record #define STRING_RECORD_EMPTY "Registo vazio na entrada fornecida." #define STRING_RECORD_JUNK_AT_EOL "Caracteres desconhecidos no fim da linha." @@ -1011,17 +998,12 @@ */ // util -#define STRING_UTIL_CONFIRM_YN " (sim/não) " #define STRING_UTIL_CONFIRM_YES "sim" #define STRING_UTIL_CONFIRM_YES_U "Sim" #define STRING_UTIL_CONFIRM_NO "não" #define STRING_UTIL_CONFIRM_ALL "todas" #define STRING_UTIL_CONFIRM_ALL_U "Todas" #define STRING_UTIL_CONFIRM_QUIT "Sair" -#define STRING_UTIL_GIBIBYTES "GiB" // |por-PRT|==|eng-USA| -#define STRING_UTIL_MEBIBYTES "MiB" // |por-PRT|==|eng-USA| -#define STRING_UTIL_KIBIBYTES "KiB" // |por-PRT|==|eng-USA| -#define STRING_UTIL_BYTES "B" // |por-PRT|==|eng-USA| // Legacy #define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'." From 3195e52e2385e47d7a57b6f0ff5c17d649c7e048 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 13:24:39 -0500 Subject: [PATCH 0182/1455] libshared: Updated to c3f1919945bd370b397314dc1ec245960a401820 --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index 9685a22c9..c3f191994 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit 9685a22c90ca6f832748f8c71bae3cfad352bc64 +Subproject commit c3f1919945bd370b397314dc1ec245960a401820 From 998b110b02c3a6b91070360ac2ad26f35ff7ee23 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 13:27:20 -0500 Subject: [PATCH 0183/1455] CmdVersion: Migrated from ViewText to Table --- src/commands/CmdVersion.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/commands/CmdVersion.cpp b/src/commands/CmdVersion.cpp index b8ec3c52d..b9763bcfc 100644 --- a/src/commands/CmdVersion.cpp +++ b/src/commands/CmdVersion.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #ifdef HAVE_COMMIT #include #endif @@ -61,15 +61,15 @@ int CmdVersion::execute (std::string& output) // Create a table for the disclaimer. int width = context.getWidth (); - ViewText disclaimer; + Table disclaimer; disclaimer.width (width); - disclaimer.add (Column::factory ("string", "")); + disclaimer.add (""); disclaimer.set (disclaimer.addRow (), 0, STRING_CMD_VERSION_MIT); // Create a table for the URL. - ViewText link; + Table link; link.width (width); - link.add (Column::factory ("string", "")); + link.add (""); link.set (link.addRow (), 0, STRING_CMD_VERSION_DOCS); Color bold; From 25d42347c8f63662c465542584b4a31b7a8625d9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 13:34:27 -0500 Subject: [PATCH 0184/1455] CmdTags: Migrated from ViewText to Table --- src/commands/CmdTags.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/CmdTags.cpp b/src/commands/CmdTags.cpp index 4187a03dc..839974cc8 100644 --- a/src/commands/CmdTags.cpp +++ b/src/commands/CmdTags.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -92,10 +92,10 @@ int CmdTags::execute (std::string& output) if (unique.size ()) { // Render a list of tags names from the map. - ViewText view; + Table view; view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_COLUMN_LABEL_TAG)); - view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_COUNT)); + view.add (STRING_COLUMN_LABEL_TAG); + view.add (STRING_COLUMN_LABEL_COUNT, false); Color bold; if (context.color ()) From 359b14884470026e983aaf01a8cbc3037f277bf2 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 13:36:06 -0500 Subject: [PATCH 0185/1455] CmdHelp: Migrated from ViewText to Table --- src/commands/CmdHelp.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index e04641b78..756f6a76d 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -72,11 +72,11 @@ int CmdHelp::execute (std::string& output) //////////////////////////////////////////////////////////////////////////////// std::string CmdHelp::composeUsage () const { - ViewText view; + Table view; view.width (context.getWidth ()); - view.add (Column::factory ("string.left", "")); - view.add (Column::factory ("string.left", "")); - view.add (Column::factory ("string.left", "")); + view.add (""); + view.add (""); + view.add (""); // Static first row. int row = view.addRow (); From 2f590bcebc1d0c72a47083a01dd6d7e7564a0f09 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 13:37:12 -0500 Subject: [PATCH 0186/1455] CmdReports: Migrated from ViewText to Table --- src/commands/CmdReports.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/CmdReports.cpp b/src/commands/CmdReports.cpp index 75dd585b4..610d018cd 100644 --- a/src/commands/CmdReports.cpp +++ b/src/commands/CmdReports.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -86,10 +86,10 @@ int CmdReports::execute (std::string& output) // Compose the output. std::stringstream out; - ViewText view; + Table view; view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_CMD_REPORTS_REPORT)); - view.add (Column::factory ("string", STRING_CMD_REPORTS_DESC)); + view.add (STRING_CMD_REPORTS_REPORT); + view.add (STRING_CMD_REPORTS_DESC); if (context.color ()) { From b5922fbfd1db476f3172e12251d26337a4ca7a20 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 13:38:53 -0500 Subject: [PATCH 0187/1455] CmdStats: Migrated from ViewText to Table --- src/commands/CmdStats.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/CmdStats.cpp b/src/commands/CmdStats.cpp index eab173f39..b77915e85 100644 --- a/src/commands/CmdStats.cpp +++ b/src/commands/CmdStats.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -159,11 +159,11 @@ int CmdStats::execute (std::string& output) } // Create a table for output. - ViewText view; + Table view; view.width (context.getWidth ()); view.intraPadding (2); - view.add (Column::factory ("string", STRING_CMD_STATS_CATEGORY)); - view.add (Column::factory ("string", STRING_CMD_STATS_DATA)); + view.add (STRING_CMD_STATS_CATEGORY); + view.add (STRING_CMD_STATS_DATA); if (context.color ()) { From ecdb96f7e1fba2ff9e247f915f7b6ed047edef44 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 13:40:46 -0500 Subject: [PATCH 0188/1455] CmdColor: Migrated from ViewText to Table --- src/commands/CmdColor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/CmdColor.cpp b/src/commands/CmdColor.cpp index 231bf3ab7..cb9474b84 100644 --- a/src/commands/CmdColor.cpp +++ b/src/commands/CmdColor.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -74,10 +74,10 @@ int CmdColor::execute (std::string& output) { out << '\n' << STRING_CMD_COLOR_HERE << '\n'; - ViewText view; + Table view; view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_CMD_COLOR_COLOR)); - view.add (Column::factory ("string", STRING_CMD_COLOR_DEFINITION)); + view.add (STRING_CMD_COLOR_COLOR); + view.add (STRING_CMD_COLOR_DEFINITION); for (auto& item : context.config) { From e73c4ef138f982bad33d21283849e97484c21e6a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 14:19:25 -0500 Subject: [PATCH 0189/1455] CmdColor: Conencted rc.color to Table::forceColor --- src/commands/CmdColor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/commands/CmdColor.cpp b/src/commands/CmdColor.cpp index cb9474b84..a751b0bce 100644 --- a/src/commands/CmdColor.cpp +++ b/src/commands/CmdColor.cpp @@ -76,6 +76,8 @@ int CmdColor::execute (std::string& output) Table view; view.width (context.getWidth ()); + if (context.config.getBoolean ("color")) + view.forceColor (); view.add (STRING_CMD_COLOR_COLOR); view.add (STRING_CMD_COLOR_DEFINITION); From 4bd8ff9834bbe6601f38d8338ab4902853bb2e9d Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 14:20:07 -0500 Subject: [PATCH 0190/1455] CmdTimesheet: Migrated from ViewText to Table --- src/commands/CmdTimesheet.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/commands/CmdTimesheet.cpp b/src/commands/CmdTimesheet.cpp index 65c1f6055..dd344d20c 100644 --- a/src/commands/CmdTimesheet.cpp +++ b/src/commands/CmdTimesheet.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -102,12 +102,12 @@ int CmdTimesheet::execute (std::string& output) << '\n'; // Render the completed table. - ViewText completed; + Table completed; completed.width (context.getWidth ()); - completed.add (Column::factory ("string", " ")); - completed.add (Column::factory ("string", STRING_COLUMN_LABEL_PROJECT)); - completed.add (Column::factory ("string.right", STRING_COLUMN_LABEL_DUE)); - completed.add (Column::factory ("string", STRING_COLUMN_LABEL_DESC)); + completed.add (" "); + completed.add (STRING_COLUMN_LABEL_PROJECT); + completed.add (STRING_COLUMN_LABEL_DUE, false); + completed.add (STRING_COLUMN_LABEL_DESC); Color label; if (context.color ()) @@ -163,12 +163,12 @@ int CmdTimesheet::execute (std::string& output) << '\n'; // Now render the started table. - ViewText started; + Table started; started.width (context.getWidth ()); - started.add (Column::factory ("string", " ")); - started.add (Column::factory ("string", STRING_COLUMN_LABEL_PROJECT)); - started.add (Column::factory ("string.right", STRING_COLUMN_LABEL_DUE)); - started.add (Column::factory ("string", STRING_COLUMN_LABEL_DESC)); + started.add (" "); + started.add (STRING_COLUMN_LABEL_PROJECT); + started.add (STRING_COLUMN_LABEL_DUE, false); + started.add (STRING_COLUMN_LABEL_DESC); started.colorHeader (label); for (auto& task : all) From d40305f5668fd2dce9a6dcd3e9f83311718370d7 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 14:21:48 -0500 Subject: [PATCH 0191/1455] CmdShow: Migrated from ViewText to Table --- src/commands/CmdShow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/CmdShow.cpp b/src/commands/CmdShow.cpp index 296c0be66..c140c1f2e 100644 --- a/src/commands/CmdShow.cpp +++ b/src/commands/CmdShow.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include extern Context context; @@ -258,10 +258,10 @@ int CmdShow::execute (std::string& output) default_values.push_back (i.first); // Create output view. - ViewText view; + Table view; view.width (width); - view.add (Column::factory ("string", STRING_CMD_SHOW_CONF_VAR)); - view.add (Column::factory ("string", STRING_CMD_SHOW_CONF_VALUE)); + view.add (STRING_CMD_SHOW_CONF_VAR); + view.add (STRING_CMD_SHOW_CONF_VALUE); Color error; Color warning; From 68253639cd004e9b6d575501ae03c45b608c6fa9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 14:22:37 -0500 Subject: [PATCH 0192/1455] CmdColumns: Migrated from ViewText to Table --- src/commands/CmdColumns.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/commands/CmdColumns.cpp b/src/commands/CmdColumns.cpp index 6f2c94f4f..ea59ff612 100644 --- a/src/commands/CmdColumns.cpp +++ b/src/commands/CmdColumns.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -70,13 +70,13 @@ int CmdColumns::execute (std::string& output) std::sort (names.begin (), names.end ()); // Render a list of column names, formats and examples. - ViewText formats; + Table 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_MODIFY)); - formats.add (Column::factory ("string", STRING_COLUMN_LABEL_STYLES)); - formats.add (Column::factory ("string", STRING_COLUMN_LABEL_EXAMPLES)); + formats.add (STRING_COLUMN_LABEL_COLUMN); + formats.add (STRING_COLUMN_LABEL_TYPE); + formats.add (STRING_COLUMN_LABEL_MODIFY); + formats.add (STRING_COLUMN_LABEL_STYLES); + formats.add (STRING_COLUMN_LABEL_EXAMPLES); if (context.color ()) { From 8eaf9f7adcaacbe23de2643f430de8ed28da7dfc Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 14:46:19 -0500 Subject: [PATCH 0193/1455] CmdCommands: Migrated from ViewText to Table --- src/commands/CmdCommands.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/commands/CmdCommands.cpp b/src/commands/CmdCommands.cpp index f11a147f2..3295fff4f 100644 --- a/src/commands/CmdCommands.cpp +++ b/src/commands/CmdCommands.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -57,18 +57,18 @@ CmdCommands::CmdCommands () //////////////////////////////////////////////////////////////////////////////// int CmdCommands::execute (std::string& output) { - ViewText view; + Table 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)); + view.add (STRING_COLUMN_LABEL_COMMAND); + view.add (STRING_COLUMN_LABEL_CATEGORY); + view.add (STRING_COLUMN_LABEL_RO, false); + view.add (STRING_COLUMN_LABEL_SHOWS_ID, false); + view.add (STRING_COLUMN_LABEL_GC, false); + view.add (STRING_COLUMN_LABEL_CONTEXT, false); + view.add (STRING_COLUMN_LABEL_FILTER, false); + view.add (STRING_COLUMN_LABEL_MODS, false); + view.add (STRING_COLUMN_LABEL_MISC, false); + view.add (STRING_COLUMN_LABEL_DESC); if (context.color ()) { From 8ca1878856e2ba4c7169c3acf0b93cac5e39467a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 14:47:12 -0500 Subject: [PATCH 0194/1455] CmdProjects: Migrated from ViewText to Table --- src/commands/CmdProjects.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/CmdProjects.cpp b/src/commands/CmdProjects.cpp index 7606472c4..819ad59d4 100644 --- a/src/commands/CmdProjects.cpp +++ b/src/commands/CmdProjects.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -105,10 +105,10 @@ int CmdProjects::execute (std::string& output) if (unique.size ()) { // Render a list of project names from the map. - ViewText view; + Table view; view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_COLUMN_LABEL_PROJECT)); - view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_TASKS)); + view.add (STRING_COLUMN_LABEL_PROJECT); + view.add (STRING_COLUMN_LABEL_TASKS, false); if (context.color ()) { From e6eac50b6c8851ad1cf9089f0d33ca052e0e95a1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 16:36:23 -0500 Subject: [PATCH 0195/1455] libshared: Updated to 1aa5c92f925a1eeec16639766994f2e6f70bcf8f --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index c3f191994..1aa5c92f9 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit c3f1919945bd370b397314dc1ec245960a401820 +Subproject commit 1aa5c92f925a1eeec16639766994f2e6f70bcf8f From aad7fa60f88697ca5a5938614756a544c65b330b Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 16:53:28 -0500 Subject: [PATCH 0196/1455] libshared: Updated to 6d35bef52da4b881fcfb9946dddb01f603e225c8 --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index 1aa5c92f9..6d35bef52 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit 1aa5c92f925a1eeec16639766994f2e6f70bcf8f +Subproject commit 6d35bef52da4b881fcfb9946dddb01f603e225c8 From dc851fe4b24623e80b7db1a60299544747f73c4b Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 16:54:11 -0500 Subject: [PATCH 0197/1455] util: Migrated obfuscateText calls to libshared --- src/util.cpp | 32 -------------------------------- src/util.h | 1 - 2 files changed, 33 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 1752b39c1..747eb1f34 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -286,38 +286,6 @@ std::string osName () #endif } -//////////////////////////////////////////////////////////////////////////////// -const std::string obfuscateText (const std::string& input) -{ - std::stringstream output; - std::string::size_type i = 0; - int character; - bool inside = false; - - while ((character = utf8_next_char (input, i))) - { - if (inside) - { - output << (char) character; - - if (character == 'm') - inside = false; - } - else - { - if (character == 033) - inside = true; - - if (inside || character == ' ') - output << (char) character; - else - output << 'x'; - } - } - - return output.str (); -} - //////////////////////////////////////////////////////////////////////////////// bool nontrivial (const std::string& input) { diff --git a/src/util.h b/src/util.h index c1ed270ef..fd06f6535 100644 --- a/src/util.h +++ b/src/util.h @@ -61,7 +61,6 @@ const std::vector extractParents ( #endif std::string osName (); -const std::string obfuscateText (const std::string&); bool nontrivial (const std::string&); int strippedLength (const std::string&); const char* optionalBlankLine (); From 79c1a942898ef012339164ede0b57afc6ee31d83 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 17:30:44 -0500 Subject: [PATCH 0198/1455] CmdInfo: Migrated from ViewText to Table --- src/commands/CmdInfo.cpp | 36 ++++++++++++++++++++++-------------- src/commands/CmdInfo.h | 4 ++-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index 7b87870ae..db4d9643f 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -99,10 +99,12 @@ int CmdInfo::execute (std::string& output) std::stringstream out; for (auto& task : filtered) { - ViewText view; + Table view; view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_COLUMN_LABEL_NAME)); - view.add (Column::factory ("string", STRING_COLUMN_LABEL_VALUE)); + if (context.config.getBoolean ("obfuscate")) + view.obfuscate (); + view.add (STRING_COLUMN_LABEL_NAME); + view.add (STRING_COLUMN_LABEL_VALUE); // If an alternating row color is specified, notify the table. if (context.color ()) @@ -407,7 +409,7 @@ int CmdInfo::execute (std::string& output) } // Create a second table, containing urgency details, if necessary. - ViewText urgencyDetails; + Table urgencyDetails; if (task.urgency () != 0.0) { if (context.color ()) @@ -420,13 +422,16 @@ int CmdInfo::execute (std::string& output) urgencyDetails.colorHeader (label); } + if (context.config.getBoolean ("obfuscate")) + urgencyDetails.obfuscate (); + urgencyDetails.width (context.getWidth ()); - urgencyDetails.add (Column::factory ("string", "")); // Attribute - urgencyDetails.add (Column::factory ("string", "")); // Value - urgencyDetails.add (Column::factory ("string", "")); // * - urgencyDetails.add (Column::factory ("string", "")); // Coefficient - urgencyDetails.add (Column::factory ("string", "")); // = - urgencyDetails.add (Column::factory ("string", "")); // Result + urgencyDetails.add (""); // Attribute + urgencyDetails.add (""); // Value + urgencyDetails.add (""); // * + urgencyDetails.add (""); // Coefficient + urgencyDetails.add (""); // = + urgencyDetails.add (""); // Result urgencyTerm (urgencyDetails, "project", task.urgency_project (), Task::urgencyProjectCoefficient); urgencyTerm (urgencyDetails, "active", task.urgency_active (), Task::urgencyActiveCoefficient); @@ -506,7 +511,7 @@ int CmdInfo::execute (std::string& output) } // Create a third table, containing undo log change details. - ViewText journal; + Table journal; // If an alternating row color is specified, notify the table. if (context.color ()) @@ -519,9 +524,12 @@ int CmdInfo::execute (std::string& output) journal.colorHeader (label); } + if (context.config.getBoolean ("obfuscate")) + journal.obfuscate (); + journal.width (context.getWidth ()); - journal.add (Column::factory ("string", STRING_COLUMN_LABEL_DATE)); - journal.add (Column::factory ("string", STRING_CMD_INFO_MODIFICATION)); + journal.add (STRING_COLUMN_LABEL_DATE); + journal.add (STRING_CMD_INFO_MODIFICATION); if (context.config.getBoolean ("journal.info") && undo.size () > 3) @@ -577,7 +585,7 @@ int CmdInfo::execute (std::string& output) //////////////////////////////////////////////////////////////////////////////// void CmdInfo::urgencyTerm ( - ViewText& view, + Table& view, const std::string& label, float measure, float coefficient) const diff --git a/src/commands/CmdInfo.h b/src/commands/CmdInfo.h index 941569e4b..e3ad8da7b 100644 --- a/src/commands/CmdInfo.h +++ b/src/commands/CmdInfo.h @@ -29,7 +29,7 @@ #include #include -#include +#include class CmdInfo : public Command { @@ -38,7 +38,7 @@ public: int execute (std::string&); private: - void urgencyTerm (ViewText&, const std::string&, float, float) const; + void urgencyTerm (Table&, const std::string&, float, float) const; }; #endif From 1e7f4510932ee136a403ee94c43d4c0ec3165400 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 17:31:21 -0500 Subject: [PATCH 0199/1455] CmdInfo: Added Table::forceColor --- src/commands/CmdInfo.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index db4d9643f..b35404d50 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -103,6 +103,8 @@ int CmdInfo::execute (std::string& output) view.width (context.getWidth ()); if (context.config.getBoolean ("obfuscate")) view.obfuscate (); + if (context.config.getBoolean ("color")) + view.forceColor (); view.add (STRING_COLUMN_LABEL_NAME); view.add (STRING_COLUMN_LABEL_VALUE); @@ -424,6 +426,8 @@ int CmdInfo::execute (std::string& output) if (context.config.getBoolean ("obfuscate")) urgencyDetails.obfuscate (); + if (context.config.getBoolean ("color")) + view.forceColor (); urgencyDetails.width (context.getWidth ()); urgencyDetails.add (""); // Attribute @@ -526,6 +530,8 @@ int CmdInfo::execute (std::string& output) if (context.config.getBoolean ("obfuscate")) journal.obfuscate (); + if (context.config.getBoolean ("color")) + journal.forceColor (); journal.width (context.getWidth ()); journal.add (STRING_COLUMN_LABEL_DATE); From c85862f894e600790ddd817ccb055f860f337d8d Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 17:36:11 -0500 Subject: [PATCH 0200/1455] Tests: Broke one tests into eight, so it is clear which one fails --- test/fontunderline.t | 49 ++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/test/fontunderline.t b/test/fontunderline.t index 52205de54..79305aace 100755 --- a/test/fontunderline.t +++ b/test/fontunderline.t @@ -36,51 +36,56 @@ from basetest import Task, TestCase class TestUnderline(TestCase): - def setUp(self): - """Executed before each test in the class""" - self.t = Task() + @classmethod + def setUpClass(cls): + cls.t = Task() + cls.t("add foo") - def test_version(self): - """Verify that underlineѕ table headers are used at the right time""" + # Test the fontunderline config variable. The following truth table defines + # the different results which are to be confirmed. + # + # color _forcecolor fontunderline result + # ----- ----------- ------------- --------- + # 0 0 0 dashes + # 0 0 1 dashes + # 0 1 0 dashes + # 0 1 1 underline + # 1* 0 0 dashes + # 1* 0 1 dashes + # 1* 1 0 dashes + # 1* 1 1 underline + # + # * When isatty (fileno (stdout)) is false, color is automatically disabled. - # Test the fontunderline config variable. The following truth table defines - # the different results which are to be confirmed. - # - # color _forcecolor fontunderline result - # ----- ----------- ------------- --------- - # 0 0 0 dashes - # 0 0 1 dashes - # 0 1 0 dashes - # 0 1 1 underline - # 1* 0 0 dashes - # 1* 0 1 dashes - # 1* 1 0 dashes - # 1* 1 1 underline - # - # * When isatty (fileno (stdout)) is false, color is automatically disabled. - - self.t("add foo") + def test_nocolor_noforce_nounderline(self): code, out, err = self.t("1 info rc.color:off rc._forcecolor:off rc.fontunderline:off") self.assertIn("--------", out) + def test_nocolor_noforce_underline(self): code, out, err = self.t("1 info rc.color:off rc._forcecolor:off rc.fontunderline:on") self.assertIn("--------", out) + def test_nocolor_force_nounderline(self): code, out, err = self.t("1 info rc.color:off rc._forcecolor:on rc.fontunderline:off") self.assertIn("--------", out) + def test_nocolor_force_underline(self): code, out, err = self.t("1 info rc.color:off rc._forcecolor:on rc.fontunderline:on") self.assertNotIn("--------", out) + def test_color_noforce_nounderline(self): code, out, err = self.t("1 info rc.color:on rc._forcecolor:off rc.fontunderline:off") self.assertIn("--------", out) + def test_color_noforce_underline(self): code, out, err = self.t("1 info rc.color:on rc._forcecolor:off rc.fontunderline:on") self.assertIn("--------", out) + def test_color_force_nounderline(self): code, out, err = self.t("1 info rc.color:on rc._forcecolor:on rc.fontunderline:off") self.assertIn("--------", out) + def test_color_force_underline(self): code, out, err = self.t("1 info rc.color:on rc._forcecolor:on rc.fontunderline:on") self.assertNotIn("--------", out) From 0a8fb12dc516146809fd6a1906d4df3a2f4b2f73 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 17:37:47 -0500 Subject: [PATCH 0201/1455] CmdCalendar: Migrated from ViewText to Table --- src/commands/CmdCalendar.cpp | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/commands/CmdCalendar.cpp b/src/commands/CmdCalendar.cpp index cd7ff484c..d500d6e0d 100644 --- a/src/commands/CmdCalendar.cpp +++ b/src/commands/CmdCalendar.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -368,10 +368,10 @@ int CmdCalendar::execute (std::string& output) // Table with holiday information if (context.config.get ("calendar.holidays") == "full") { - ViewText holTable; + Table holTable; holTable.width (context.getWidth ()); - holTable.add (Column::factory ("string", STRING_CMD_CAL_LABEL_DATE)); - holTable.add (Column::factory ("string", STRING_CMD_CAL_LABEL_HOL)); + holTable.add (STRING_CMD_CAL_LABEL_DATE); + holTable.add (STRING_CMD_CAL_LABEL_HOL); holTable.colorHeader (color_label); std::map > hm; // we need to store multiple holidays per day @@ -434,32 +434,32 @@ std::string CmdCalendar::renderMonths ( // Build table for the number of months to be displayed. Color label (context.config.get ("color.label")); - ViewText view; + Table view; view.colorHeader (label); view.width (context.getWidth ()); for (int i = 0 ; i < (monthsPerLine * 8); i += 8) { if (weekStart == 1) { - view.add (Column::factory ("string.right", "")); - 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))); + view.add ("", false); + view.add (utf8_substr (ISO8601d::dayName (1), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (2), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (3), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (4), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (5), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (6), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (0), 0, 2), false); } else { - view.add (Column::factory ("string.right", "")); - 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))); + view.add ("", false); + view.add (utf8_substr (ISO8601d::dayName (0), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (1), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (2), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (3), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (4), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (5), 0, 2), false); + view.add (utf8_substr (ISO8601d::dayName (6), 0, 2), false); } } From 6db3ff7c068448de7e7f8a41e6d77f21259112c3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 20:02:49 -0500 Subject: [PATCH 0202/1455] CmdHistory: Migrated from ViewText to Table --- src/commands/CmdHistory.cpp | 50 +++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/src/commands/CmdHistory.cpp b/src/commands/CmdHistory.cpp index a8d71eb7f..562b69abd 100644 --- a/src/commands/CmdHistory.cpp +++ b/src/commands/CmdHistory.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -103,14 +103,16 @@ int CmdHistoryMonthly::execute (std::string& output) } // Now build the view. - ViewText view; + Table view; + if (context.config.getBoolean ("color")) + view.forceColor (); view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_CMD_HISTORY_YEAR)); - view.add (Column::factory ("string", STRING_CMD_HISTORY_MONTH)); - view.add (Column::factory ("string.right", STRING_CMD_HISTORY_ADDED)); - view.add (Column::factory ("string.right", STRING_CMD_HISTORY_COMP)); - view.add (Column::factory ("string.right", STRING_CMD_HISTORY_DEL)); - view.add (Column::factory ("string.right", STRING_CMD_HISTORY_NET)); + view.add (STRING_CMD_HISTORY_YEAR); + view.add (STRING_CMD_HISTORY_MONTH); + view.add (STRING_CMD_HISTORY_ADDED, false); + view.add (STRING_CMD_HISTORY_COMP, false); + view.add (STRING_CMD_HISTORY_DEL, false); + view.add (STRING_CMD_HISTORY_NET, false); if (context.color ()) { @@ -268,13 +270,15 @@ int CmdHistoryAnnual::execute (std::string& output) } // Now build the view. - ViewText view; + Table view; + if (context.config.getBoolean ("color")) + view.forceColor (); view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_CMD_HISTORY_YEAR)); - view.add (Column::factory ("string.right", STRING_CMD_HISTORY_ADDED)); - view.add (Column::factory ("string.right", STRING_CMD_HISTORY_COMP)); - view.add (Column::factory ("string.right", STRING_CMD_HISTORY_DEL)); - view.add (Column::factory ("string.right", STRING_CMD_HISTORY_NET)); + view.add (STRING_CMD_HISTORY_YEAR); + view.add (STRING_CMD_HISTORY_ADDED, false); + view.add (STRING_CMD_HISTORY_COMP, false); + view.add (STRING_CMD_HISTORY_DEL, false); + view.add (STRING_CMD_HISTORY_NET, false); if (context.color ()) { @@ -432,11 +436,13 @@ int CmdGHistoryMonthly::execute (std::string& output) int widthOfBar = context.getWidth () - 15; // 15 == strlen ("2008 September ") // Now build the view. - ViewText view; + Table view; + if (context.config.getBoolean ("color")) + view.forceColor (); view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_CMD_GHISTORY_YEAR)); - view.add (Column::factory ("string", STRING_CMD_GHISTORY_MONTH)); - view.add (Column::factory ("string.left_fixed", STRING_CMD_GHISTORY_NUMBER)); + view.add (STRING_CMD_GHISTORY_YEAR); + view.add (STRING_CMD_GHISTORY_MONTH); + view.add (STRING_CMD_GHISTORY_NUMBER); // Fixed. Color color_add (context.config.get ("color.history.add")); Color color_done (context.config.get ("color.history.done")); @@ -632,10 +638,12 @@ int CmdGHistoryAnnual::execute (std::string& output) int widthOfBar = context.getWidth () - 5; // 5 == strlen ("YYYY ") // Now build the view. - ViewText view; + Table view; + if (context.config.getBoolean ("color")) + view.forceColor (); view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_CMD_GHISTORY_YEAR)); - view.add (Column::factory ("string.left_fixed", STRING_CMD_GHISTORY_NUMBER)); + view.add (STRING_CMD_GHISTORY_YEAR); + view.add (STRING_CMD_GHISTORY_NUMBER); // Fixed. Color color_add (context.config.get ("color.history.add")); Color color_done (context.config.get ("color.history.done")); From c95aa9fa3c6de442e436f427e72f9160d7b8363d Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 20:10:21 -0500 Subject: [PATCH 0203/1455] TDB2: Migrated from ViewText to Table --- src/TDB2.cpp | 15 ++++++++------- src/TDB2.h | 1 - 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/TDB2.cpp b/src/TDB2.cpp index b8caae2b0..69790c5c6 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -1043,12 +1044,12 @@ void TDB2::show_diff ( // Attributes are all there is, so figure the different attribute names // between before and after. - ViewText view; + Table view; view.width (context.getWidth ()); view.intraPadding (2); - view.add (Column::factory ("string", "")); - view.add (Column::factory ("string", STRING_TDB2_UNDO_PRIOR)); - view.add (Column::factory ("string", STRING_TDB2_UNDO_CURRENT)); + view.add (""); + view.add (STRING_TDB2_UNDO_PRIOR); + view.add (STRING_TDB2_UNDO_CURRENT); Color label (context.config.get ("color.label")); view.colorHeader (label); @@ -1141,11 +1142,11 @@ void TDB2::show_diff ( Task after (current); // Generate table header. - ViewText view; + Table view; view.width (context.getWidth ()); view.intraPadding (2); - view.add (Column::factory ("string", "")); - view.add (Column::factory ("string", "")); + view.add (""); + view.add (""); int row = view.addRow (); view.set (row, 0, STRING_TDB2_DIFF_PREV, color_red); diff --git a/src/TDB2.h b/src/TDB2.h index a830355e4..0b6f7ea34 100644 --- a/src/TDB2.h +++ b/src/TDB2.h @@ -33,7 +33,6 @@ #include #include #include -#include #include #include From 1658998864c5984ce859f8c53971cb76fb3ae2d8 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 20:14:13 -0500 Subject: [PATCH 0204/1455] CmdSummary: Migrated from ViewText to Table --- src/commands/CmdSummary.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index f18d41278..b84ed1b56 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -131,13 +131,13 @@ int CmdSummary::execute (std::string& output) } // Create a table for output. - ViewText view; + Table view; view.width (context.getWidth ()); - view.add (Column::factory ("string", STRING_CMD_SUMMARY_PROJECT)); - view.add (Column::factory ("string.right", STRING_CMD_SUMMARY_REMAINING)); - view.add (Column::factory ("string.right", STRING_CMD_SUMMARY_AVG_AGE)); - view.add (Column::factory ("string.right", STRING_CMD_SUMMARY_COMPLETE)); - view.add (Column::factory ("string.left_fixed", "0% 100%")); + view.add (STRING_CMD_SUMMARY_PROJECT); + view.add (STRING_CMD_SUMMARY_REMAINING, false); + view.add (STRING_CMD_SUMMARY_AVG_AGE, false); + view.add (STRING_CMD_SUMMARY_COMPLETE, false); + view.add ("0% 100%"); Color bar_color; Color bg_color; From 392e74cd70b057f1878b17c656764dc5fc0a0143 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 20:23:36 -0500 Subject: [PATCH 0205/1455] ViewText: Eliminated --- src/CMakeLists.txt | 1 - src/ViewText.cpp | 316 --------------------------------------------- src/ViewText.h | 92 ------------- test/view.t.cpp | 36 +----- 4 files changed, 1 insertion(+), 444 deletions(-) delete mode 100644 src/ViewText.cpp delete mode 100644 src/ViewText.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6ae2e22a..cd7bfb672 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,7 +23,6 @@ add_library (task CLI2.cpp CLI2.h TLSClient.cpp TLSClient.h Variant.cpp Variant.h ViewTask.cpp ViewTask.h - ViewText.cpp ViewText.h dependency.cpp feedback.cpp i18n.h diff --git a/src/ViewText.cpp b/src/ViewText.cpp deleted file mode 100644 index 98dc225ba..000000000 --- a/src/ViewText.cpp +++ /dev/null @@ -1,316 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -extern Context context; - -//////////////////////////////////////////////////////////////////////////////// -ViewText::ViewText () -: _width (0) -, _left_margin (0) -, _header (0) -, _odd (0) -, _even (0) -, _intra_padding (1) -, _intra_odd (0) -, _intra_even (0) -, _extra_padding (0) -, _extra_odd (0) -, _extra_even (0) -, _truncate_lines (0) -, _truncate_rows (0) -, _lines (0) -, _rows (0) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -ViewText::~ViewText () -{ - for (auto& col : _columns) - delete col; - - _columns.clear (); -} - -//////////////////////////////////////////////////////////////////////////////// -int ViewText::addRow () -{ - _data.push_back (std::vector (_columns.size (), "")); - _color.push_back (std::vector (_columns.size (), Color::nocolor)); - return _data.size () - 1; -} - -//////////////////////////////////////////////////////////////////////////////// -void ViewText::set (int row, int col, const std::string& value, Color color) -{ - _data[row][col] = value; - - if (color.nontrivial () && - context.color ()) - _color[row][col] = color; -} - -//////////////////////////////////////////////////////////////////////////////// -void ViewText::set (int row, int col, int value, Color color) -{ - std::string string_value = format (value); - _data[row][col] = string_value; - - if (color.nontrivial () && - context.color ()) - _color[row][col] = color; -} - -//////////////////////////////////////////////////////////////////////////////// -void ViewText::set (int row, int col, Color color) -{ - if (color.nontrivial () && - context.color ()) - _color[row][col] = color; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string ViewText::render () -{ - bool const obfuscate = context.config.getBoolean ("obfuscate"); - - // Determine minimal, ideal column widths. - std::vector minimal; - std::vector ideal; - for (unsigned int col = 0; col < _columns.size (); ++col) - { - // Headers factor in to width calculations. - unsigned int global_min = utf8_width (_columns[col]->label ()); - unsigned int global_ideal = global_min; - - for (unsigned int row = 0; row < _data.size (); ++row) - { - // Determine minimum and ideal width for this column. - unsigned int min = 0; - unsigned int ideal = 0; - _columns[col]->measure (_data[row][col], min, ideal); - - if (min > global_min) global_min = min; - if (ideal > global_ideal) global_ideal = ideal; - - // If a fixed-width column was just measured, there is no point repeating - // the measurement for all tasks. - if (_columns[col]->is_fixed_width ()) - break; - } - - minimal.push_back (global_min); - ideal.push_back (global_ideal); - } - - // Sum the minimal widths. - int sum_minimal = 0; - for (auto& c : minimal) - sum_minimal += c; - - // Sum the ideal widths. - int sum_ideal = 0; - for (auto& c : ideal) - sum_ideal += c; - - // Calculate final column widths. - int overage = _width - - _left_margin - - (2 * _extra_padding) - - ((_columns.size () - 1) * _intra_padding); - - std::vector widths; - if (sum_ideal <= overage) - widths = ideal; - else if (sum_minimal > overage || overage < 0) - widths = minimal; - else if (overage > 0) - { - widths = minimal; - overage -= sum_minimal; - - // Spread 'overage' among columns where width[i] < ideal[i] - while (overage) - { - for (unsigned int i = 0; i < _columns.size () && overage; ++i) - { - if (widths[i] < ideal[i]) - { - ++widths[i]; - --overage; - } - } - } - } - - // Compose column headers. - unsigned int max_lines = 0; - std::vector > headers; - for (unsigned int c = 0; c < _columns.size (); ++c) - { - headers.push_back (std::vector ()); - _columns[c]->renderHeader (headers[c], widths[c], _header); - - if (headers[c].size () > max_lines) - max_lines = headers[c].size (); - } - - // Output string. - std::string out; - _lines = 0; - - // Render column headers. - std::string left_margin = std::string (_left_margin, ' '); - std::string extra = std::string (_extra_padding, ' '); - std::string intra = std::string (_intra_padding, ' '); - - std::string extra_odd = context.color () ? _extra_odd.colorize (extra) : extra; - std::string extra_even = context.color () ? _extra_even.colorize (extra) : extra; - std::string intra_odd = context.color () ? _intra_odd.colorize (intra) : intra; - std::string intra_even = context.color () ? _intra_even.colorize (intra) : intra; - - for (unsigned int i = 0; i < max_lines; ++i) - { - out += left_margin + extra; - - for (unsigned int c = 0; c < _columns.size (); ++c) - { - if (c) - out += intra; - - if (headers[c].size () < max_lines - i) - out += _header.colorize (std::string (widths[c], ' ')); - else - out += headers[c][i]; - } - - out += extra; - - // Trim right. - out.erase (out.find_last_not_of (" ") + 1); - out += "\n"; - - // Stop if the line limit is exceeded. - if (++_lines >= _truncate_lines && _truncate_lines != 0) - return out; - } - - // Compose, render columns, in sequence. - _rows = 0; - std::vector > cells; - for (unsigned int row = 0; row < _data.size (); ++row) - { - max_lines = 0; - - // Alternate rows based on |s % 2| - bool odd = (row % 2) ? true : false; - Color row_color = odd ? _odd : _even; - - // TODO row_color.blend (provided color); - // TODO Problem: colors for columns are specified, not rows, - // therefore there are only cell colors, not intra colors. - - Color cell_color; - for (unsigned int col = 0; col < _columns.size (); ++col) - { - if (context.color ()) - { - cell_color = row_color; - cell_color.blend (_color[row][col]); - } - - cells.push_back (std::vector ()); - _columns[col]->render (cells[col], _data[row][col], widths[col], cell_color); - - if (cells[col].size () > max_lines) - max_lines = cells[col].size (); - - if (obfuscate) - if (_columns[col]->type () == "string") - for (unsigned int line = 0; line < cells[col].size (); ++line) - cells[col][line] = obfuscateText (cells[col][line]); - } - - for (unsigned int i = 0; i < max_lines; ++i) - { - out += left_margin + (odd ? extra_odd : extra_even); - - for (unsigned int col = 0; col < _columns.size (); ++col) - { - if (col) - { - if (row_color.nontrivial ()) - out += row_color.colorize (intra); - else - out += (odd ? intra_odd : intra_even); - } - - if (i < cells[col].size ()) - out += cells[col][i]; - else - { - if (context.color ()) - { - cell_color = row_color; - cell_color.blend (_color[row][col]); - - out += cell_color.colorize (std::string (widths[col], ' ')); - } - else - out += std::string (widths[col], ' '); - } - } - - out += (odd ? extra_odd : extra_even); - - // Trim right. - out.erase (out.find_last_not_of (" ") + 1); - out += "\n"; - - // Stop if the line limit is exceeded. - if (++_lines >= _truncate_lines && _truncate_lines != 0) - return out; - } - - cells.clear (); - - // Stop if the row limit is exceeded. - if (++_rows >= _truncate_rows && _truncate_rows != 0) - return out; - } - - return out; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/ViewText.h b/src/ViewText.h deleted file mode 100644 index f2b7804d0..000000000 --- a/src/ViewText.h +++ /dev/null @@ -1,92 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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_VIEWTEXT -#define INCLUDED_VIEWTEXT - -#include -#include -#include -#include -#include - -class ViewText -{ -public: - ViewText (); - ~ViewText (); - - // View specifications. - void add (Column* col) { _columns.push_back (col); } - void width (int width) { _width = width; } - void leftMargin (int margin) { _left_margin = margin; } - void colorHeader (Color& c) { _header = c; } - void colorOdd (Color& c) { _odd = c; } - void colorEven (Color& c) { _even = c; } - void intraPadding (int padding) { _intra_padding = padding; } - void intraColorOdd (Color& c) { _intra_odd = c; } - void intraColorEven (Color& c) { _intra_even = c; } - void extraPadding (int padding) { _extra_padding = padding; } - void extraColorOdd (Color& c) { _extra_odd = c; } - void extraColorEven (Color& c) { _extra_even = c; } - void truncateLines (int n) { _truncate_lines = n; } - void truncateRows (int n) { _truncate_rows = n; } - int lines () { return _lines; } - int rows () { return (int) _data.size (); } - - // Data provision. - int addRow (); - void set (int, int, const std::string&, Color color = Color::nocolor); - void set (int, int, int, Color color = Color::nocolor); - void set (int, int, Color); - - // View rendering. - std::string render (); - -private: - std::vector > _data; - std::vector > _color; - std::vector _columns; - int _width; - int _left_margin; - Color _header; - Color _odd; - Color _even; - int _intra_padding; - Color _intra_odd; - Color _intra_even; - int _extra_padding; - Color _extra_odd; - Color _extra_even; - int _truncate_lines; - int _truncate_rows; - int _lines; - int _rows; -}; - -#endif -//////////////////////////////////////////////////////////////////////////////// - diff --git a/test/view.t.cpp b/test/view.t.cpp index 95e8334bd..26956d8f1 100644 --- a/test/view.t.cpp +++ b/test/view.t.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -42,7 +41,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { - UnitTest t (2); + UnitTest t (1); // Ensure environment has no influence. unsetenv ("TASKDATA"); @@ -145,39 +144,6 @@ int main (int, char**) // Now render a string-only grid. context.config.set ("fontunderline", false); Color single_cell ("bold white on red"); - - ViewText string_view; - string_view.width (context.getWidth ()); - string_view.leftMargin (4); - string_view.extraPadding (0); - string_view.intraPadding (1); - string_view.colorHeader (header_color); - string_view.colorOdd (odd_color); - string_view.colorEven (even_color); - string_view.intraColorOdd (odd_color); - string_view.intraColorEven (even_color); - - string_view.add (Column::factory ("string", "One")); - string_view.add (Column::factory ("string", "Two")); - string_view.add (Column::factory ("string", "Three")); - - int row = string_view.addRow (); - string_view.set (row, 0, "top left"); - string_view.set (row, 1, "top center"); - string_view.set (row, 2, "top right"); - - row = string_view.addRow (); - string_view.set (row, 0, "bottom left", single_cell); - string_view.set (row, 1, "bottom center, containing sufficient text that " - "wrapping will occur because it exceeds all " - "reasonable values for default width. Even in a " - "very wide terminal window. Just look at the " - "lengths we must go to, to get passing unit tests " - "and not flaky tests."); - string_view.set (row, 2, "bottom right"); - - std::cout << string_view.render (); - t.ok (string_view.lines () > 4, "View::lines > 4"); } catch (const std::string& e) From 1805cf733b1c49c558bc818a2df43ea091f87d88 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 21:19:50 -0500 Subject: [PATCH 0206/1455] Config: Migrated form ISO8601d to Datetime --- src/Config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index 794dd5b16..6d904e5d8 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -490,7 +490,7 @@ void Config::createDefaultRC (const std::string& rc, const std::string& data) auto loc = _defaults.find ("data.location=~/.task"); // loc+0^ +14^ +21^ - ISO8601d now; + Datetime now; std::stringstream contents; contents << "# [Created by " << PACKAGE_STRING From c1bf321631c24ff38cb251e1ca00a6737e700758 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 17 Dec 2016 21:22:31 -0500 Subject: [PATCH 0207/1455] TDB2: Migrated from ISO8601d to Datetime --- src/TDB2.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/TDB2.cpp b/src/TDB2.cpp index 69790c5c6..1961a8e9f 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -348,7 +348,7 @@ Task TF2::load_task (const std::string& line) // or needs to be 'woken'. void TF2::load_gc (Task& task) { - ISO8601d now; + Datetime now; std::string status = task.get ("status"); if (status == "pending" || @@ -358,7 +358,7 @@ void TF2::load_gc (Task& task) } else if (status == "waiting") { - ISO8601d wait (task.get_date ("wait")); + Datetime wait (task.get_date ("wait")); if (wait < now) { task.set ("status", "pending"); @@ -709,7 +709,7 @@ void TDB2::update ( // old // new // --- - undo.add_line ("time " + ISO8601d ().toEpochString () + '\n'); + undo.add_line ("time " + Datetime ().toEpochString () + '\n'); undo.add_line ("old " + original.composeF4 () + '\n'); undo.add_line ("new " + task.composeF4 () + '\n'); undo.add_line ("---\n"); @@ -728,7 +728,7 @@ void TDB2::update ( // time

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 delta 66719 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 Date: Wed, 24 Feb 2016 23:19:15 -0500 Subject: [PATCH 0004/1455] Cleanup: Removed deprecated 'alias._query' setting --- ChangeLog | 6 ++++-- DEVELOPER | 8 ++++---- NEWS | 2 +- src/legacy.cpp | 8 ++++---- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index a1ed000df..e61c55b83 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2.6.0 () - +- Removed deprecated 'alias._query' setting. + ------ current release --------------------------- 2.5.1 (2016-02-24) 8b4ae3b54b44dfbd00b96cdd6dceb8dfe7cc1ea0 @@ -112,6 +114,8 @@ - The 'run_all' script was not correctly using exit code 0 when all tests pass (thanks to Gordon Ball). +------ old releases ------------------------------ + 2.5.0 (2015-10-21) dd5968a61b1fab258b38879cfdbb7d67f1bcd550 - TW-20 Task edit loses annotation precision, causing journal updating code @@ -325,8 +329,6 @@ added. - When GC is turned off, disable the query shortcuts, which no longer apply. ------- old releases ------------------------------ - 2.4.4 (2015-05-10) df49aaba126484b668c41d3ff9301f8d8ec49987 - TW-69 wait dates relative to due date (thanks to John Florian). diff --git a/DEVELOPER b/DEVELOPER index 6af9d9631..8eb0b44cc 100644 --- a/DEVELOPER +++ b/DEVELOPER @@ -10,7 +10,7 @@ How to Build Taskwarrior Obtain and build code: $ git clone https://git.tasktools.org/scm/tm/task.git task.git $ cd task.git - $ git checkout 2.5.0 # Latest dev branch + $ git checkout 2.6.0 # Latest dev branch $ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither. $ make VERBOSE=1 # Shows details @@ -158,11 +158,11 @@ Work in Progress Current Codebase Condition 'master' branch: - - 2.4.4 Current release, locked. + - 2.5.1 Current release, locked. - '2.5.0' branch: + '2.6.0' branch: - Current development branch no plans yet. --- -2015-09-07 Updated for 2.5.0 +2016-02-24 Updated for 2.6.0 diff --git a/NEWS b/NEWS index 448a6ed99..df4002e1c 100644 --- a/NEWS +++ b/NEWS @@ -17,7 +17,7 @@ Newly Deprecated Features in Taskwarrior 2.6.0 Removed Features in 2.6.0 - - + - Removed 'alias._query' default configuration. Known Issues diff --git a/src/legacy.cpp b/src/legacy.cpp index 6139505fd..be4039cf0 100644 --- a/src/legacy.cpp +++ b/src/legacy.cpp @@ -96,22 +96,21 @@ std::string legacyCheckForDeprecatedVariables () for (auto& it : context.config) { // 2014-07-04: report.*.limit removed. + // 2016-02-24: alias._query removed. + // Deprecated in 2.5.0. // 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); + // Deprecated in 2.5.0. 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); - // Deprecated in 2.5.0. if (it.first == "urgency.inherit.coefficient") deprecated.push_back (it.first); @@ -140,6 +139,7 @@ std::string legacyCheckForDeprecatedColumns () { if (it.first.find ("report") == 0) { + // Deprecated in 2.0.0 std::string value = context.config.get (it.first); if (value.find ("entry_time") != std::string::npos || value.find ("start_time") != std::string::npos || From bfefd247c4f463ee594f76fc411a39d5b7e5d11f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 24 Feb 2016 23:26:39 -0500 Subject: [PATCH 0005/1455] Context: Combined interactive.cpp and Context.cpp --- src/CMakeLists.txt | 1 - src/Context.cpp | 72 ++++++++++++++++++++++++++++++ src/interactive.cpp | 105 -------------------------------------------- 3 files changed, 72 insertions(+), 106 deletions(-) delete mode 100644 src/interactive.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 35c182b56..fde10cd3c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,7 +31,6 @@ set (task_SRCS CLI2.cpp CLI2.h dependency.cpp feedback.cpp i18n.h - interactive.cpp legacy.cpp recur.cpp rules.cpp diff --git a/src/Context.cpp b/src/Context.cpp index c1195be8c..98edcd635 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -42,10 +42,18 @@ #include #include #include + #ifdef HAVE_COMMIT #include #endif +#include +#include + +#ifdef SOLARIS +#include +#endif + // Supported modifiers, synonyms on the same line. static const char* modifierNames[] = { @@ -469,6 +477,70 @@ int Context::dispatch (std::string &out) return commands["help"]->execute (out); } +//////////////////////////////////////////////////////////////////////////////// +int Context::getWidth () +{ + // Determine window size. + int width = config.getInteger ("defaultwidth"); + + // A zero width value means 'infinity', which is approximated here by 2^16. + if (width == 0) + return 65536; + + if (config.getBoolean ("detection")) + { + if (terminal_width == 0 && + terminal_height == 0) + { + unsigned short buff[4]; + if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &buff) != -1) + { + terminal_height = buff[0]; + terminal_width = buff[1]; + } + } + + width = terminal_width; + + // 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 + // an odd color wrapping problem. + if (config.getBoolean ("avoidlastcolumn")) + --width; + } + + return width; +} + +//////////////////////////////////////////////////////////////////////////////// +int Context::getHeight () +{ + // Determine window size. + int height = config.getInteger ("defaultheight"); + + // A zero height value means 'infinity', which is approximated here by 2^16. + if (height == 0) + return 65536; + + if (config.getBoolean ("detection")) + { + if (terminal_width == 0 && + terminal_height == 0) + { + unsigned short buff[4]; + if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &buff) != -1) + { + terminal_height = buff[0]; + terminal_width = buff[1]; + } + } + + height = terminal_height; + } + + return height; +} + //////////////////////////////////////////////////////////////////////////////// bool Context::color () { diff --git a/src/interactive.cpp b/src/interactive.cpp deleted file mode 100644 index 1b1dc54ba..000000000 --- a/src/interactive.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -#ifdef SOLARIS -#include -#endif - -//////////////////////////////////////////////////////////////////////////////// -int Context::getWidth () -{ - // Determine window size. - int width = config.getInteger ("defaultwidth"); - - // A zero width value means 'infinity', which is approximated here by 2^16. - if (width == 0) - return 65536; - - if (config.getBoolean ("detection")) - { - if (terminal_width == 0 && - terminal_height == 0) - { - unsigned short buff[4]; - if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &buff) != -1) - { - terminal_height = buff[0]; - terminal_width = buff[1]; - } - } - - width = terminal_width; - - // 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 - // an odd color wrapping problem. - if (config.getBoolean ("avoidlastcolumn")) - --width; - } - - return width; -} - -//////////////////////////////////////////////////////////////////////////////// -int Context::getHeight () -{ - // Determine window size. - int height = config.getInteger ("defaultheight"); - - // A zero height value means 'infinity', which is approximated here by 2^16. - if (height == 0) - return 65536; - - if (config.getBoolean ("detection")) - { - if (terminal_width == 0 && - terminal_height == 0) - { - unsigned short buff[4]; - if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &buff) != -1) - { - terminal_height = buff[0]; - terminal_width = buff[1]; - } - } - - height = terminal_height; - } - - return height; -} - -//////////////////////////////////////////////////////////////////////////////// From 549b970e4958c0e31b03a03db3af006c4597a31b Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 24 Feb 2016 23:43:23 -0500 Subject: [PATCH 0006/1455] Cleanup: Removed redundant processing of OS name --- src/DOM.cpp | 31 ++++--------------------------- src/commands/CmdDiagnostics.cpp | 26 +------------------------- src/util.cpp | 27 +++++++++++++++++++++++++++ src/util.h | 2 ++ 4 files changed, 34 insertions(+), 52 deletions(-) diff --git a/src/DOM.cpp b/src/DOM.cpp index 4d49cf352..f938412c2 100644 --- a/src/DOM.cpp +++ b/src/DOM.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include extern Context context; @@ -58,14 +59,14 @@ bool getDOM (const std::string& name, Variant& value) if (name == "") return false; - int len = name.length (); + auto len = name.length (); Nibbler n (name); // rc. --> context.config if (len > 3 && ! name.compare (0, 3, "rc.", 3)) { - std::string key = name.substr (3); + auto key = name.substr (3); auto c = context.config.find (key); if (c != context.config.end ()) { @@ -117,8 +118,6 @@ bool getDOM (const std::string& name, Variant& value) throw format (STRING_DOM_UNREC, name); } - // TODO stats. - // system. --> Implement locally. if (len > 7 && ! name.compare (0, 7, "system.", 7)) @@ -133,29 +132,7 @@ bool getDOM (const std::string& name, Variant& value) // OS type. else if (name == "system.os") { -#if defined (DARWIN) - value = Variant ("Darwin"); -#elif defined (SOLARIS) - value = Variant ("Solaris"); -#elif defined (CYGWIN) - value = Variant ("Cygwin"); -#elif defined (HAIKU) - value = Variant ("Haiku"); -#elif defined (OPENBSD) - value = Variant ("OpenBSD"); -#elif defined (FREEBSD) - value = Variant ("FreeBSD"); -#elif defined (NETBSD) - value = Variant ("NetBSD"); -#elif defined (LINUX) - value = Variant ("Linux"); -#elif defined (KFREEBSD) - value = Variant ("GNU/kFreeBSD"); -#elif defined (GNUHURD) - value = Variant ("GNU/Hurd"); -#else - value = Variant (STRING_DOM_UNKNOWN); -#endif + value = Variant (osName ()); return true; } else diff --git a/src/commands/CmdDiagnostics.cpp b/src/commands/CmdDiagnostics.cpp index 9ccb47abd..77076ed44 100644 --- a/src/commands/CmdDiagnostics.cpp +++ b/src/commands/CmdDiagnostics.cpp @@ -79,31 +79,7 @@ int CmdDiagnostics::execute (std::string& output) << bold.colorize (PACKAGE_STRING) << "\n"; - out << " " << STRING_CMD_DIAG_PLATFORM << ": " - << -#if defined (DARWIN) - "Darwin" -#elif defined (SOLARIS) - "Solaris" -#elif defined (CYGWIN) - "Cygwin" -#elif defined (HAIKU) - "Haiku" -#elif defined (OPENBSD) - "OpenBSD" -#elif defined (FREEBSD) - "FreeBSD" -#elif defined (NETBSD) - "NetBSD" -#elif defined (LINUX) - "Linux" -#elif defined (KFREEBSD) - "GNU/kFreeBSD" -#elif defined (GNUHURD) - "GNU/Hurd" -#else - STRING_CMD_DIAG_UNKNOWN -#endif + out << " " << STRING_CMD_DIAG_PLATFORM << ": " << osName () << "\n\n"; // Compiler. diff --git a/src/util.cpp b/src/util.cpp index 9b07c09af..0d7c6e3a8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -484,4 +484,31 @@ time_t timegm (struct tm *tm) #endif //////////////////////////////////////////////////////////////////////////////// +std::string osName () +{ +#if defined (DARWIN) + return "Darwin"; +#elif defined (SOLARIS) + return "Solaris"; +#elif defined (CYGWIN) + return "Cygwin"; +#elif defined (HAIKU) + return "Haiku"; +#elif defined (OPENBSD) + return "OpenBSD"; +#elif defined (FREEBSD) + return "FreeBSD"; +#elif defined (NETBSD) + return "NetBSD"; +#elif defined (LINUX) + return "Linux"; +#elif defined (KFREEBSD) + return "GNU/kFreeBSD"; +#elif defined (GNUHURD) + return "GNU/Hurd"; +#else + return STRING_DOM_UNKNOWN; +#endif +} +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.h b/src/util.h index cec0ae8b5..078fadbe6 100644 --- a/src/util.h +++ b/src/util.h @@ -65,5 +65,7 @@ const std::vector extractParents ( time_t timegm (struct tm *tm); #endif +std::string osName (); + #endif //////////////////////////////////////////////////////////////////////////////// From 88f6872190efe1cfbac31fab8e788fc36a7a3d09 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 24 Feb 2016 23:55:46 -0500 Subject: [PATCH 0007/1455] Rules: Improved use of 'const' and 'auto' --- src/rules.cpp | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/rules.cpp b/src/rules.cpp index 192cc425f..dc4accd76 100644 --- a/src/rules.cpp +++ b/src/rules.cpp @@ -53,7 +53,7 @@ void initializeColorRules () // 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; - for (auto& v : context.config) + for (const auto& v : context.config) { if (! v.first.compare (0, 6, "color.", 6)) { @@ -70,7 +70,7 @@ void initializeColorRules () std::vector precedence; split (precedence, context.config.get ("rule.precedence.color"), ','); - for (auto& p : precedence) + for (const auto& p : precedence) { // Add the leading "color." string. std::string rule = "color." + p; @@ -90,13 +90,12 @@ void initializeColorRules () //////////////////////////////////////////////////////////////////////////////// static void applyColor (const Color& base, Color& c, bool merge) { - if (merge) - c.blend (base); - else - c = base; + if (merge) + c.blend (base); + else + c = base; } - //////////////////////////////////////////////////////////////////////////////// static void colorizeBlocked (Task& task, const Color& base, Color& c, bool merge) { @@ -154,8 +153,8 @@ static void colorizeProject (Task& task, const std::string& rule, const Color& b // Observe the case sensitivity setting. bool sensitive = context.config.getBoolean ("search.case.sensitive"); - std::string project = task.get ("project"); - std::string rule_trunc = rule.substr (14); + auto project = task.get ("project"); + auto rule_trunc = rule.substr (14); // Match project names leftmost. if (rule_trunc.length () <= project.length ()) @@ -181,7 +180,7 @@ static void colorizeTagNone (Task& task, const Color& base, Color& c, bool merge 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"); + auto sensitive = context.config.getBoolean ("search.case.sensitive"); // The easiest thing to check is the description, because it is just one // attribute. @@ -192,10 +191,10 @@ static void colorizeKeyword (Task& task, const std::string& rule, const Color& b // first match. else { - for (auto& it : task.data) + for (const auto& att : task.data) { - if (! it.first.compare (0, 11, "annotation_", 11) && - find (it.second, rule.substr (14), sensitive) != std::string::npos) + if (! att.first.compare (0, 11, "annotation_", 11) && + find (att.second, rule.substr (14), sensitive) != std::string::npos) { applyColor (base, c, merge); return; @@ -208,7 +207,7 @@ static void colorizeKeyword (Task& task, const std::string& rule, const Color& b static void colorizeUDA (Task& task, const std::string& rule, const Color& base, Color& c, bool merge) { // Is the rule color.uda.name.value or color.uda.name? - size_t pos = rule.find (".", 10); + auto pos = rule.find (".", 10); if (pos == std::string::npos) { if (task.has (rule.substr (10))) @@ -216,8 +215,8 @@ static void colorizeUDA (Task& task, const std::string& rule, const Color& base, } else { - const std::string uda = rule.substr (10, pos - 10); - const std::string val = rule.substr (pos + 1); + auto uda = rule.substr (10, pos - 10); + auto val = rule.substr (pos + 1); if ((val == "none" && ! task.has (uda)) || task.get (uda) == val) applyColor (base, c, merge); @@ -229,7 +228,7 @@ static void colorizeDue (Task& task, const Color& base, Color& c, bool merge) { if (task.has ("due")) { - Task::status status = task.getStatus (); + auto status = task.getStatus (); if (status != Task::completed && status != Task::deleted && task.getDateState ("due") == Task::dateAfterToday) @@ -242,8 +241,8 @@ static void colorizeDueToday (Task& task, const Color& base, Color& c, bool merg { if (task.has ("due")) { - Task::status status = task.getStatus (); - Task::dateState dateState = task.getDateState ("due"); + auto status = task.getStatus (); + auto dateState = task.getDateState ("due"); if (status != Task::completed && status != Task::deleted && (dateState == Task::dateLaterToday || dateState == Task::dateEarlierToday)) @@ -256,7 +255,7 @@ static void colorizeOverdue (Task& task, const Color& base, Color& c, bool merge { if (task.has ("due")) { - Task::status status = task.getStatus (); + auto status = task.getStatus (); if (status != Task::completed && status != Task::deleted && task.getDateState ("due") == Task::dateBeforeToday) @@ -296,7 +295,7 @@ void autoColorize (Task& task, Color& c) return; } - bool merge = context.config.getBoolean ("rule.color.merge"); + auto 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 From 2d20f4d57b04bcf219a8d25d8343879777c83bdd Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 25 Feb 2016 00:19:38 -0500 Subject: [PATCH 0008/1455] Cleanup: Converted all sprintf to snprintf --- src/Task.cpp | 2 +- src/Variant.cpp | 4 ++-- src/commands/CmdBurndown.cpp | 16 ++++++++-------- src/commands/CmdColor.cpp | 2 +- src/commands/CmdLogo.cpp | 4 ++-- src/commands/CmdSummary.cpp | 2 +- src/recur.cpp | 18 +++++------------- src/util.cpp | 8 ++++---- 8 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/Task.cpp b/src/Task.cpp index 35191c9b6..5dee6f25e 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -180,7 +180,7 @@ const std::string Task::identifier (bool shortened /* = false */) const void Task::setAsNow (const std::string& att) { char now[16]; - sprintf (now, "%u", (unsigned int) time (NULL)); + snprintf (now, 16, "%u", (unsigned int) time (NULL)); set (att, now); recalc_urgency = true; diff --git a/src/Variant.cpp b/src/Variant.cpp index c99b31525..1de474e85 100644 --- a/src/Variant.cpp +++ b/src/Variant.cpp @@ -1782,7 +1782,7 @@ void Variant::cast (const enum type new_type) case type_string: { char temp[24]; - sprintf (temp, "%d", _integer); + snprintf (temp, 24, "%d", _integer); _string = temp; } break; @@ -1800,7 +1800,7 @@ void Variant::cast (const enum type new_type) case type_string: { char temp[24]; - sprintf (temp, "%g", _real); + snprintf (temp, 24, "%g", _real); _string = temp; } break; diff --git a/src/commands/CmdBurndown.cpp b/src/commands/CmdBurndown.cpp index 3cf04e2fc..5151b3712 100644 --- a/src/commands/CmdBurndown.cpp +++ b/src/commands/CmdBurndown.cpp @@ -467,9 +467,9 @@ std::string Chart::render () // Draw y-axis labels. char label [12]; - sprintf (label, "%*d", _max_label, _labels[2]); + snprintf (label, 12, "%*d", _max_label, _labels[2]); _grid.replace (LOC (1, _max_label - strlen (label)), strlen (label), label); - sprintf (label, "%*d", _max_label, _labels[1]); + snprintf (label, 12, "%*d", _max_label, _labels[1]); _grid.replace (LOC (1 + (_graph_height / 2), _max_label - strlen (label)), strlen (label), label); _grid.replace (LOC (_graph_height + 1, _max_label - 1), 1, "0"); @@ -527,7 +527,7 @@ std::string Chart::render () calculateRates (); char rate[12]; if (_net_fix_rate != 0.0) - sprintf (rate, "%.1f/d", _net_fix_rate); + snprintf (rate, 12, "%.1f/d", _net_fix_rate); else strcpy (rate, "-"); @@ -729,24 +729,24 @@ void Chart::generateBars () std::string month = ISO8601d::monthName (cursor.month ()); bar._major_label = month.substr (0, 3); - sprintf (str, "%02d", cursor.day ()); + snprintf (str, 12, "%02d", cursor.day ()); bar._minor_label = str; } break; case 'W': // year/week - sprintf (str, "%d", cursor.year ()); + snprintf (str, 12, "%d", cursor.year ()); bar._major_label = str; - sprintf (str, "%02d", cursor.weekOfYear (0)); + snprintf (str, 12, "%02d", cursor.weekOfYear (0)); bar._minor_label = str; break; case 'M': // year/month - sprintf (str, "%d", cursor.year ()); + snprintf (str, 12, "%d", cursor.year ()); bar._major_label = str; - sprintf (str, "%02d", cursor.month ()); + snprintf (str, 12, "%02d", cursor.month ()); bar._minor_label = str; break; } diff --git a/src/commands/CmdColor.cpp b/src/commands/CmdColor.cpp index 64672d271..6fe0e3b2e 100644 --- a/src/commands/CmdColor.cpp +++ b/src/commands/CmdColor.cpp @@ -219,7 +219,7 @@ int CmdColor::execute (std::string& output) char label [12]; for (int g = 0; g < 6; ++g) { - sprintf (label, " %d", g); + snprintf (label, 12, " %d", g); out << Color::colorize (label, "bold green"); for (int r = 0; r < 6; ++r) { diff --git a/src/commands/CmdLogo.cpp b/src/commands/CmdLogo.cpp index 8a1c2c408..744c7e641 100644 --- a/src/commands/CmdLogo.cpp +++ b/src/commands/CmdLogo.cpp @@ -108,7 +108,7 @@ int CmdLogo::execute (std::string& output) { value += 167; char block [24]; - sprintf (block, "\033[48;5;%dm \033[0m", value); + snprintf (block, 24, "\033[48;5;%dm \033[0m", value); output += block; } } @@ -122,7 +122,7 @@ int CmdLogo::execute (std::string& output) { value += 167; char block [24]; - sprintf (block, "\033[48;5;%dm \033[0m", value); + snprintf (block, 24, "\033[48;5;%dm \033[0m", value); output += block; } } diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index 90da8328d..04e06ce4b 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -199,7 +199,7 @@ int CmdSummary::execute (std::string& output) char percent[12] = "0%"; if (c + p) - sprintf (percent, "%d%%", 100 * c / (c + p)); + snprintf (percent, 12, "%d%%", 100 * c / (c + p)); view.set (row, 3, percent); processed.push_back (i.first); } diff --git a/src/recur.cpp b/src/recur.cpp index 2c8b3f670..6ee2179fc 100644 --- a/src/recur.cpp +++ b/src/recur.cpp @@ -37,7 +37,6 @@ #include #include #include - #include #include #include @@ -80,10 +79,10 @@ void handleRecurrence () } // Get the mask from the parent task. - std::string mask = t.get ("mask"); + auto mask = t.get ("mask"); // Iterate over the due dates, and check each against the mask. - bool changed = false; + auto changed = false; unsigned int i = 0; for (auto& d : due) { @@ -97,18 +96,14 @@ void handleRecurrence () rec.set ("uuid", uuid ()); // New UUID. rec.set ("parent", t.get ("uuid")); // Remember mom. rec.setAsNow ("entry"); // New entry date. - - char dueDate[16]; - sprintf (dueDate, "%u", (unsigned int) d.toEpoch ()); - rec.set ("due", dueDate); // Store generated due date. + rec.set ("due", format (d.toEpoch ())); if (t.has ("wait")) { 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.set ("wait", format ((due + (old_wait - old_due)).toEpoch ())); rec.setStatus (Task::waiting); mask += 'W'; } @@ -118,10 +113,7 @@ void handleRecurrence () rec.setStatus (Task::pending); } - char indexMask[12]; - sprintf (indexMask, "%u", (unsigned int) i); - rec.set ("imask", indexMask); // Store index into mask. - + rec.set ("imask", i); rec.remove ("mask"); // Remove the mask of the parent. // Add the new task to the DB. diff --git a/src/util.cpp b/src/util.cpp index 0d7c6e3a8..2db86148d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -155,10 +155,10 @@ std::string formatBytes (size_t bytes) { char formatted[24]; - if (bytes >= 995000000) sprintf (formatted, "%.1f %s", (bytes / 1000000000.0), STRING_UTIL_GIBIBYTES); - else if (bytes >= 995000) sprintf (formatted, "%.1f %s", (bytes / 1000000.0), STRING_UTIL_MEBIBYTES); - else if (bytes >= 995) sprintf (formatted, "%.1f %s", (bytes / 1000.0), STRING_UTIL_KIBIBYTES); - else sprintf (formatted, "%d %s", (int)bytes, STRING_UTIL_BYTES); + if (bytes >= 995000000) snprintf (formatted, 24, "%.1f %s", (bytes / 1000000000.0), STRING_UTIL_GIBIBYTES); + else if (bytes >= 995000) snprintf (formatted, 24, "%.1f %s", (bytes / 1000000.0), STRING_UTIL_MEBIBYTES); + else if (bytes >= 995) snprintf (formatted, 24, "%.1f %s", (bytes / 1000.0), STRING_UTIL_KIBIBYTES); + else snprintf (formatted, 24, "%d %s", (int)bytes, STRING_UTIL_BYTES); return Lexer::commify (formatted); } From bc34397e9b3e856925e27a9ecbf13be0fc3b25bd Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 25 Feb 2016 00:21:52 -0500 Subject: [PATCH 0009/1455] calc: Uses osName() to reduce string literals --- src/calc.cpp | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/calc.cpp b/src/calc.cpp index be0b83f33..681f6af00 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include Context context; @@ -83,29 +84,7 @@ int main (int argc, char** argv) { std::cout << "\n" << format (STRING_CMD_VERSION_BUILT, "calc", VERSION) -#if defined (DARWIN) - << "darwin" -#elif defined (SOLARIS) - << "solaris" -#elif defined (CYGWIN) - << "cygwin" -#elif defined (HAIKU) - << "haiku" -#elif defined (OPENBSD) - << "openbsd" -#elif defined (FREEBSD) - << "freebsd" -#elif defined (NETBSD) - << "netbsd" -#elif defined (LINUX) - << "linux" -#elif defined (KFREEBSD) - << "gnu-kfreebsd" -#elif defined (GNUHURD) - << "gnu-hurd" -#else - << STRING_CMD_VERSION_UNKNOWN -#endif + << osName () << "\n" << STRING_CMD_VERSION_COPY << "\n" From eb09df0e6a0a48e14b67671a121c771d5f221df5 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 28 Feb 2016 11:09:00 -0500 Subject: [PATCH 0010/1455] TD-64: sync conflict deleted all annotations of the task - Thanks to Markus Beppler, Konstantin Vorobyev. --- AUTHORS | 2 +- ChangeLog | 2 ++ src/Task.cpp | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 32b8d3752..1e2e01e2c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -126,7 +126,7 @@ The following submitted code, packages or analysis, and deserve special thanks: Sunil Joshi Misty De Meo Kent R. Spillner - Konstantin + Konstantin Vorobyev Thanks to the following, who submitted detailed bug reports and excellent suggestions: diff --git a/ChangeLog b/ChangeLog index e61c55b83..6d03e9694 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2.6.0 () - +- TD-64 sync conflict deleted all annotations of the task + (thanks to Markus Beppler, Konstantin Vorobyev). - Removed deprecated 'alias._query' setting. ------ current release --------------------------- diff --git a/src/Task.cpp b/src/Task.cpp index 5dee6f25e..23e3a44a5 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -270,6 +270,9 @@ void Task::set (const std::string& name, const std::string& value) { data[name] = json::decode (value); + if (! name.compare (0, 11, "annotation_", 11)) + ++annotation_count; + recalc_urgency = true; } @@ -286,6 +289,9 @@ void Task::remove (const std::string& name) { if (data.erase (name)) recalc_urgency = true; + + if (! name.compare (0, 11, "annotation_", 11)) + --annotation_count; } //////////////////////////////////////////////////////////////////////////////// From e220ee884c05dcc331657a97004e8caeb4536c7b Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 28 Feb 2016 11:19:29 -0500 Subject: [PATCH 0011/1455] =?UTF-8?q?TW-1741:=20Warning=20"ignoring=20retu?= =?UTF-8?q?rn=20value=20of=20=E2=80=98int=20ftruncate"=20while=20doing=20m?= =?UTF-8?q?ake=20on=20xubuntu15.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Thanks to Sunil Joshi. --- src/FS.cpp | 4 +++- src/l10n/deu-DEU.h | 1 + src/l10n/eng-USA.h | 1 + src/l10n/epo-RUS.h | 1 + src/l10n/esp-ESP.h | 1 + src/l10n/fra-FRA.h | 1 + src/l10n/ita-ITA.h | 1 + src/l10n/jpn-JPN.h | 1 + src/l10n/pol-POL.h | 1 + src/l10n/por-PRT.h | 1 + 10 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/FS.cpp b/src/FS.cpp index 04a84b80b..72bb9c72d 100644 --- a/src/FS.cpp +++ b/src/FS.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -556,7 +557,8 @@ void File::truncate () open (); if (_fh) - (void) ftruncate (_h, 0); + if (ftruncate (_h, 0)) + throw format (STRING_FILE_TRUNCATE, errno, strerror (errno)); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/l10n/deu-DEU.h b/src/l10n/deu-DEU.h index cbf9e5aa1..7f74bff50 100644 --- a/src/l10n/deu-DEU.h +++ b/src/l10n/deu-DEU.h @@ -796,6 +796,7 @@ // File #define STRING_FILE_PERMS "Taskwarrior hat die erforderlichen Rechte auf '{1}' nicht." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 559ce72d5..b97777e13 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -794,6 +794,7 @@ // File #define STRING_FILE_PERMS "Taskwarrior does not have the correct permissions for '{1}'." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." diff --git a/src/l10n/epo-RUS.h b/src/l10n/epo-RUS.h index 1ca0d4fae..30ff8b1c4 100644 --- a/src/l10n/epo-RUS.h +++ b/src/l10n/epo-RUS.h @@ -796,6 +796,7 @@ // File #define STRING_FILE_PERMS "Taskwarrior ne havas la bezonatan permeson por '{1}'." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index a1d855704..225993a90 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -804,6 +804,7 @@ // File #define STRING_FILE_PERMS "Taskwarrior no tiene los permisos adecuados para '{1}'." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "El proyecto '{1}' ha cambiado." diff --git a/src/l10n/fra-FRA.h b/src/l10n/fra-FRA.h index 84c3996a8..98a25db4a 100644 --- a/src/l10n/fra-FRA.h +++ b/src/l10n/fra-FRA.h @@ -796,6 +796,7 @@ // File #define STRING_FILE_PERMS "Taskwarrior does not have the correct permissions for '{1}'." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." diff --git a/src/l10n/ita-ITA.h b/src/l10n/ita-ITA.h index eeb3125c1..d804d44e2 100644 --- a/src/l10n/ita-ITA.h +++ b/src/l10n/ita-ITA.h @@ -795,6 +795,7 @@ // File #define STRING_FILE_PERMS "Taskwarrior non dispone dei permessi corretti per '{1}'." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "Il progetto '{1}' è stato modificat." diff --git a/src/l10n/jpn-JPN.h b/src/l10n/jpn-JPN.h index b19f8298f..ac6b31f4c 100644 --- a/src/l10n/jpn-JPN.h +++ b/src/l10n/jpn-JPN.h @@ -796,6 +796,7 @@ // File #define STRING_FILE_PERMS "Taskwarrior does not have the correct permissions for '{1}'." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." diff --git a/src/l10n/pol-POL.h b/src/l10n/pol-POL.h index 7d0fd121c..dec6b975e 100644 --- a/src/l10n/pol-POL.h +++ b/src/l10n/pol-POL.h @@ -796,6 +796,7 @@ // File #define STRING_FILE_PERMS "Taskwarrior nie posiada praw dostępu do '{1}'." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." diff --git a/src/l10n/por-PRT.h b/src/l10n/por-PRT.h index 556467d6e..9d2ef8b74 100644 --- a/src/l10n/por-PRT.h +++ b/src/l10n/por-PRT.h @@ -796,6 +796,7 @@ // File #define STRING_FILE_PERMS "O taskwarrior não encontrou as permissões corretas em '{1}'." +#define STRING_FILE_TRUNCATE "Could not truncate file: {1} {2}" // helpers #define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed." From 7af844fde599ea1d1e5cc82dcd7367611e627e52 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 17 Mar 2016 17:17:22 -0400 Subject: [PATCH 0012/1455] CmdDiagnostics: Typo --- src/commands/CmdDiagnostics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/CmdDiagnostics.cpp b/src/commands/CmdDiagnostics.cpp index 77076ed44..a71fa5190 100644 --- a/src/commands/CmdDiagnostics.cpp +++ b/src/commands/CmdDiagnostics.cpp @@ -280,7 +280,7 @@ int CmdDiagnostics::execute (std::string& output) << credentials << "\n\n"; - // Disaply hook status. + // Display hook status. Path hookLocation (context.config.get ("data.location")); hookLocation += "hooks"; From 96d6fb145fca1b3e0e41ff3ea3f5d973a951462e Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sat, 19 Mar 2016 20:18:41 +0100 Subject: [PATCH 0013/1455] TDB2: Add capability to purge tasks out of data files --- src/TDB2.cpp | 33 ++++++++++++++++++++++++++++++--- src/TDB2.h | 4 ++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/TDB2.cpp b/src/TDB2.cpp index 22dff8a72..5d501eb9b 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -218,6 +218,21 @@ bool TF2::modify_task (const Task& task) return false; } +//////////////////////////////////////////////////////////////////////////////// +bool TF2::purge_task (const Task& task) +{ + // Bail out if task is not found in this file + std::string uuid = task.get ("uuid"); + if (!has (uuid)) + return false; + + // Mark the task to be purged + _purged_tasks.insert (uuid); + _dirty = true; + + return true; +} + //////////////////////////////////////////////////////////////////////////////// void TF2::add_line (const std::string& line) { @@ -248,7 +263,7 @@ void TF2::commit () if (_dirty) { // Special case: added but no modified means just append to the file. - if (!_modified_tasks.size () && + if (!_modified_tasks.size () && !_purged_tasks.size () && (_added_tasks.size () || _added_lines.size ())) { if (_file.open ()) @@ -284,7 +299,9 @@ void TF2::commit () // Only write out _tasks, because any deltas have already been applied. _file.append (std::string("")); // Seek to end of file for (auto& task : _tasks) - _file.write_raw (task.composeF4 () + "\n"); + // Skip over the tasks that are marked to be purged + if (_purged_tasks.find (task.get ("uuid")) == _purged_tasks.end ()) + _file.write_raw (task.composeF4 () + "\n"); // Write out all the added lines. _file.append (_added_lines); @@ -492,6 +509,7 @@ void TF2::clear () _tasks.clear (); _added_tasks.clear (); _modified_tasks.clear (); + _purged_tasks.clear (); _lines.clear (); _added_lines.clear (); _I2U.clear (); @@ -565,17 +583,19 @@ const std::string TF2::dump () std::string tasks = green.colorize (rightJustifyZero ((int) _tasks.size (), 4)); std::string tasks_added = red.colorize (rightJustifyZero ((int) _added_tasks.size (), 3)); std::string tasks_modified = yellow.colorize (rightJustifyZero ((int) _modified_tasks.size (), 3)); + std::string tasks_purged = red.colorize (rightJustifyZero ((int) _purged_tasks.size (), 3)); std::string lines = green.colorize (rightJustifyZero ((int) _lines.size (), 4)); std::string lines_added = red.colorize (rightJustifyZero ((int) _added_lines.size (), 3)); char buffer[256]; // Composed string is actually 246 bytes. Yikes. - snprintf (buffer, 256, "%14s %s %s T%s+%s~%s L%s+%s", + snprintf (buffer, 256, "%14s %s %s T%s+%s~%s-%s L%s+%s", label.c_str (), mode.c_str (), hygiene.c_str (), tasks.c_str (), tasks_added.c_str (), tasks_modified.c_str (), + tasks_purged.c_str (), lines.c_str (), lines_added.c_str ()); @@ -649,6 +669,13 @@ void TDB2::modify (Task& task, bool add_to_backlog /* = true */) update (task, add_to_backlog); } +//////////////////////////////////////////////////////////////////////////////// +void TDB2::purge (Task& task) +{ + // Delete the task from completed.data + completed.purge_task (task); +} + //////////////////////////////////////////////////////////////////////////////// void TDB2::update ( Task& task, diff --git a/src/TDB2.h b/src/TDB2.h index b05aa21a7..a830355e4 100644 --- a/src/TDB2.h +++ b/src/TDB2.h @@ -28,6 +28,7 @@ #define INCLUDED_TDB2 #include +#include #include #include #include @@ -54,6 +55,7 @@ public: void add_task (Task&); bool modify_task (const Task&); + bool purge_task (const Task&); void add_line (const std::string&); void clear_tasks (); void clear_lines (); @@ -90,6 +92,7 @@ public: std::vector _added_tasks; std::vector _modified_tasks; + std::unordered_set _purged_tasks; std::vector _lines; std::vector _added_lines; File _file; @@ -110,6 +113,7 @@ public: void set_location (const std::string&); void add (Task&, bool add_to_backlog = true); void modify (Task&, bool add_to_backlog = true); + void purge (Task&); void commit (); void get_changes (std::vector &); void revert (); From 1caa9daec010f89981a18e20c05f716d07fe5cd4 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sat, 19 Mar 2016 21:18:41 +0100 Subject: [PATCH 0014/1455] CmdPurge: Add initial implementation --- src/commands/CMakeLists.txt | 1 + src/commands/CmdPurge.cpp | 80 +++++++++++++++++++++++++++++++++++++ src/commands/CmdPurge.h | 41 +++++++++++++++++++ src/commands/Command.cpp | 2 + src/l10n/eng-USA.h | 2 + 5 files changed, 126 insertions(+) create mode 100644 src/commands/CmdPurge.cpp create mode 100644 src/commands/CmdPurge.h diff --git a/src/commands/CMakeLists.txt b/src/commands/CMakeLists.txt index cd6f7a519..575e351e7 100644 --- a/src/commands/CMakeLists.txt +++ b/src/commands/CMakeLists.txt @@ -40,6 +40,7 @@ set (commands_SRCS Command.cpp Command.h CmdModify.cpp CmdModify.h CmdPrepend.cpp CmdPrepend.h CmdProjects.cpp CmdProjects.h + CmdPurge.cpp CmdPurge.h CmdReports.cpp CmdReports.h CmdShow.cpp CmdShow.h CmdStart.cpp CmdStart.h diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp new file mode 100644 index 000000000..5ca665efe --- /dev/null +++ b/src/commands/CmdPurge.cpp @@ -0,0 +1,80 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2006 - 2016, 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; + +//////////////////////////////////////////////////////////////////////////////// +CmdPurge::CmdPurge () +{ + _keyword = "purge"; + _usage = "task purge"; + _description = STRING_CMD_PURGE_USAGE; + _read_only = false; + _displays_id = false; + _needs_confirm = true; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::operation; +} + +//////////////////////////////////////////////////////////////////////////////// +int CmdPurge::execute (std::string&) +{ + int rc = 0; + int count = 0; + + // Apply filter. + Filter filter; + std::vector filtered; + filter.subset (filtered); + if (filtered.size () == 0) + { + context.footnote (STRING_FEEDBACK_NO_TASKS_SP); + return 1; + } + + for (auto& task : filtered) + { + if (task.getStatus () == Task::deleted) + { + context.tdb2.purge (task); + count++; + } + } + + return rc; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdPurge.h b/src/commands/CmdPurge.h new file mode 100644 index 000000000..8e9c76446 --- /dev/null +++ b/src/commands/CmdPurge.h @@ -0,0 +1,41 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2006 - 2016, 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_CMDPURGE +#define INCLUDED_CMDPURGE + +#include +#include + +class CmdPurge : public Command +{ +public: + CmdPurge (); + int execute (std::string&); +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 29025d994..4783afc68 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -145,6 +146,7 @@ void Command::factory (std::map & all) c = new CmdModify (); all[c->keyword ()] = c; c = new CmdPrepend (); all[c->keyword ()] = c; c = new CmdProjects (); all[c->keyword ()] = c; + c = new CmdPurge (); all[c->keyword ()] = c; c = new CmdReports (); all[c->keyword ()] = c; c = new CmdShow (); all[c->keyword ()] = c; c = new CmdShowRaw (); all[c->keyword ()] = c; diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index b97777e13..cbc038b76 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -396,6 +396,8 @@ #define STRING_CMD_DUPLICATE_1 "Duplicated {1} task." #define STRING_CMD_DUPLICATE_N "Duplicated {1} tasks." +#define STRING_CMD_PURGE_USAGE "Removes the specified task from the data files. Causes permanent loss of data." + #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "Task not started." #define STRING_CMD_START_ALREADY "Task {1} '{2}' already started." From b3652800da29f089ddf549e86d4ea8a2ba33e3d7 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sat, 19 Mar 2016 23:05:59 +0100 Subject: [PATCH 0015/1455] CmdPurge: Remove purged tasks from dependencies --- src/commands/CmdPurge.cpp | 23 ++++++++++++++++++++--- src/l10n/eng-USA.h | 2 ++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index 5ca665efe..2156e9777 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -29,6 +29,7 @@ #include #include #include +#include extern Context context; @@ -55,9 +56,10 @@ int CmdPurge::execute (std::string&) int rc = 0; int count = 0; - // Apply filter. Filter filter; std::vector filtered; + + // Apply filter. filter.subset (filtered); if (filtered.size () == 0) { @@ -67,13 +69,28 @@ int CmdPurge::execute (std::string&) for (auto& task : filtered) { + std::string uuid = task.get ("uuid"); + if (task.getStatus () == Task::deleted) { - context.tdb2.purge (task); - count++; + context.tdb2.purge (task); + count++; + + // Remove dependencies on the task being purged + for (auto& blockedConst: context.tdb2.all_tasks ()) + { + Task& blocked = const_cast(blockedConst); + if (blocked.has ("depends") && + blocked.get ("depends").find (uuid) != std::string::npos) + { + blocked.removeDependency (uuid); + context.tdb2.modify (blocked); + } + } } } + feedback_affected (count == 1 ? STRING_CMD_PURGE_1 : STRING_CMD_PURGE_N, count); return rc; } diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index cbc038b76..750e9dc61 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -397,6 +397,8 @@ #define STRING_CMD_DUPLICATE_N "Duplicated {1} tasks." #define STRING_CMD_PURGE_USAGE "Removes the specified task from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "Task not started." From 2b882605317fd3f00b76068dde7479f34bfc4a74 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 01:40:29 +0100 Subject: [PATCH 0016/1455] CmdPurge: Require GC run prior to execution Since TDB2::purge method allows purging of the tasks only on competed.data file, we need to make sure that all the tasks that were supposed to be moved to completed.data have been moved - in other words, we need to run GC. This allows for diract usage of purge after delete, that is: $ task delete $ task purge working as expected. --- src/commands/CmdPurge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index 2156e9777..12cf14c3a 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -42,7 +42,7 @@ CmdPurge::CmdPurge () _read_only = false; _displays_id = false; _needs_confirm = true; - _needs_gc = false; + _needs_gc = true; _uses_context = true; _accepts_filter = true; _accepts_modifications = false; From 293ccfdb02dc4ac7377ab6d3c18135e9c931421b Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 01:45:20 +0100 Subject: [PATCH 0017/1455] DEVELOPER: Use multiple jobs during make --- DEVELOPER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEVELOPER b/DEVELOPER index 8eb0b44cc..1fbc9197a 100644 --- a/DEVELOPER +++ b/DEVELOPER @@ -12,7 +12,7 @@ How to Build Taskwarrior $ cd task.git $ git checkout 2.6.0 # Latest dev branch $ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither. - $ make VERBOSE=1 # Shows details + $ make VERBOSE=1 -j8 # Shows details, builds using 8 jobs Running Test Suite: $ cd tests From cda4e505e67097d877eee9743731f5d4d2128232 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 02:03:42 +0100 Subject: [PATCH 0018/1455] tests: Add coverage for purge command --- test/purge.t | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 test/purge.t diff --git a/test/purge.t b/test/purge.t new file mode 100755 index 000000000..7b8363683 --- /dev/null +++ b/test/purge.t @@ -0,0 +1,79 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +############################################################################### +# +# Copyright 2006 - 2016, Paul Beckingham, Federico Hernandez. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# http://www.opensource.org/licenses/mit-license.php +# +############################################################################### + +import sys +import os +import unittest +# Ensure python finds the local simpletap module +sys.path.append(os.path.dirname(os.path.abspath(__file__))) + +from basetest import Task, TestCase + + +class TestDelete(TestCase): + def setUp(self): + self.t = Task() + + def test_add_delete_purge(self): + """Verify that add/delete/purge successfully purges a task""" + self.t("add one") + uuid = self.t("_get 1.uuid")[1].strip() + + code, out, err = self.t("1 delete", input="y\n") + self.assertIn("Deleted 1 task.", out) + + code, out, err = self.t(uuid + " purge") + self.assertIn("Purged 1 task.", out) + + code, out, err = self.t("uuids") + self.assertNotIn(uuid, out) + + def test_purge_remove_deps(self): + """Verify that purge command removes dependency references""" + self.t("add one") + self.t("add two dep:1") + uuid = self.t("_get 1.uuid")[1].strip() + + code, out, err = self.t("1 delete", input="y\n") + self.assertIn("Deleted 1 task.", out) + + code, out, err = self.t(uuid + " purge") + self.assertIn("Purged 1 task.", out) + + code, out, err = self.t("uuids") + self.assertNotIn(uuid, out) + + dependencies = self.t("_get 1.depends")[1].strip() + self.assertNotIn(uuid, dependencies) + + +if __name__ == "__main__": + from simpletap import TAPTestRunner + unittest.main(testRunner=TAPTestRunner()) + +# vim: ai sts=4 et sw=4 ft=python From fd4cf8fec423472460b092fd7cb17b5850a70447 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 19 Mar 2016 21:51:34 -0400 Subject: [PATCH 0019/1455] Docs: Added MAKEFLAGS example --- DEVELOPER | 1 + 1 file changed, 1 insertion(+) diff --git a/DEVELOPER b/DEVELOPER index 1fbc9197a..10c24f159 100644 --- a/DEVELOPER +++ b/DEVELOPER @@ -13,6 +13,7 @@ How to Build Taskwarrior $ git checkout 2.6.0 # Latest dev branch $ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither. $ make VERBOSE=1 -j8 # Shows details, builds using 8 jobs + # Alternately 'export MAKEFLAGS=-j 8'. Running Test Suite: $ cd tests From 6bca92a488cbd7a4e5238f07ea77bfd6180bee20 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 19 Mar 2016 21:57:01 -0400 Subject: [PATCH 0020/1455] L10N: Propagated new strings to all LANGS --- src/l10n/deu-DEU.h | 4 ++++ src/l10n/eng-USA.h | 2 +- src/l10n/epo-RUS.h | 4 ++++ src/l10n/esp-ESP.h | 4 ++++ src/l10n/fra-FRA.h | 4 ++++ src/l10n/ita-ITA.h | 4 ++++ src/l10n/jpn-JPN.h | 4 ++++ src/l10n/pol-POL.h | 4 ++++ src/l10n/por-PRT.h | 4 ++++ 9 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/l10n/deu-DEU.h b/src/l10n/deu-DEU.h index 7f74bff50..e3b4a003c 100644 --- a/src/l10n/deu-DEU.h +++ b/src/l10n/deu-DEU.h @@ -398,6 +398,10 @@ #define STRING_CMD_DUPLICATE_1 "{1} Aufgabe verdoppelt." #define STRING_CMD_DUPLICATE_N "{1} Aufgaben verdoppelt." +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." + #define STRING_CMD_START_USAGE "Kennzeichnet die gewählte Aufgabe als begonnen." #define STRING_CMD_START_NO "Aufgabe nicht begonnen." #define STRING_CMD_START_ALREADY "Aufgabe {1} '{2}' ist bereits gestartet." diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 750e9dc61..857628cf4 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -396,7 +396,7 @@ #define STRING_CMD_DUPLICATE_1 "Duplicated {1} task." #define STRING_CMD_DUPLICATE_N "Duplicated {1} tasks." -#define STRING_CMD_PURGE_USAGE "Removes the specified task from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." diff --git a/src/l10n/epo-RUS.h b/src/l10n/epo-RUS.h index 30ff8b1c4..1412ce5b9 100644 --- a/src/l10n/epo-RUS.h +++ b/src/l10n/epo-RUS.h @@ -398,6 +398,10 @@ #define STRING_CMD_DUPLICATE_1 "Kopiis {1} taskon." #define STRING_CMD_DUPLICATE_N "Kopiis {1} taskojn." +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." + #define STRING_CMD_START_USAGE "Markas la specifatan taskon kiel ekita" #define STRING_CMD_START_NO "Ne ekis taskon." #define STRING_CMD_START_ALREADY "Tasko {1} '{2}' jam ekita." diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index 225993a90..15e3f638d 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -403,6 +403,10 @@ #define STRING_CMD_DUPLICATE_1 "Duplicada {1} tarea." #define STRING_CMD_DUPLICATE_N "Duplicadas {1} tareas." +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." + #define STRING_CMD_START_USAGE "Marca la tarea especificada como comenzada" #define STRING_CMD_START_NO "Tarea no comenzada." #define STRING_CMD_START_ALREADY "Tarea {1} '{2}' ya comenzada." diff --git a/src/l10n/fra-FRA.h b/src/l10n/fra-FRA.h index 98a25db4a..8ca0a4f0e 100644 --- a/src/l10n/fra-FRA.h +++ b/src/l10n/fra-FRA.h @@ -398,6 +398,10 @@ #define STRING_CMD_DUPLICATE_1 "Duplicated {1} task." #define STRING_CMD_DUPLICATE_N "Duplicated {1} tasks." +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." + #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "Tâche non démarrée." #define STRING_CMD_START_ALREADY "Tâche {1} '{2}' déjà démarré." diff --git a/src/l10n/ita-ITA.h b/src/l10n/ita-ITA.h index d804d44e2..f5a6e48ac 100644 --- a/src/l10n/ita-ITA.h +++ b/src/l10n/ita-ITA.h @@ -397,6 +397,10 @@ #define STRING_CMD_DUPLICATE_1 "Task {1} duplicato." #define STRING_CMD_DUPLICATE_N "Task {1} duplicati." +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." + #define STRING_CMD_START_USAGE "Contrassegna i task specificati come avviati" #define STRING_CMD_START_NO "Task non avviato." #define STRING_CMD_START_ALREADY "Task {1} '{2}' già avviati." diff --git a/src/l10n/jpn-JPN.h b/src/l10n/jpn-JPN.h index ac6b31f4c..a6d8b0c7b 100644 --- a/src/l10n/jpn-JPN.h +++ b/src/l10n/jpn-JPN.h @@ -398,6 +398,10 @@ #define STRING_CMD_DUPLICATE_1 "重複した {1} タスク。" #define STRING_CMD_DUPLICATE_N "重複した {1} タスク。" +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." + #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "タスク は開始していません。" #define STRING_CMD_START_ALREADY "タスク {1} '{2}' は既に開始しています。" diff --git a/src/l10n/pol-POL.h b/src/l10n/pol-POL.h index dec6b975e..529599321 100644 --- a/src/l10n/pol-POL.h +++ b/src/l10n/pol-POL.h @@ -398,6 +398,10 @@ #define STRING_CMD_DUPLICATE_1 "Skopiowano {1} zadanie." #define STRING_CMD_DUPLICATE_N "Skopiowano {1} zadań." +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." + #define STRING_CMD_START_USAGE "Oznacza zadanie jako uruchomione" #define STRING_CMD_START_NO "Zadanie nie uruchomione" #define STRING_CMD_START_ALREADY "Zadanie {1} '{2}' jest już uruchomione" diff --git a/src/l10n/por-PRT.h b/src/l10n/por-PRT.h index 9d2ef8b74..f310a6d2d 100644 --- a/src/l10n/por-PRT.h +++ b/src/l10n/por-PRT.h @@ -398,6 +398,10 @@ #define STRING_CMD_DUPLICATE_1 "Duplicada {1} tarefa." #define STRING_CMD_DUPLICATE_N "Duplicadas {1} tarefas." +#define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_1 "Purged {1} task." +#define STRING_CMD_PURGE_N "Purged {1} tasks." + #define STRING_CMD_START_USAGE "Assinala a tarefa especificada como iniciada" #define STRING_CMD_START_NO "Tarefa não iniciada." #define STRING_CMD_START_ALREADY "Tarefa {1} '{2}' já iniciada." From fd0d2fc91731aa8d2387468a214cc79fceb761cc Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 10:02:29 +0100 Subject: [PATCH 0021/1455] CmdPurge: Prompt before purging a task --- src/commands/CmdPurge.cpp | 27 ++++++++++++++++++--------- src/l10n/eng-USA.h | 1 + 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index 12cf14c3a..1d9143e43 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -30,6 +30,7 @@ #include #include #include +#include extern Context context; @@ -73,18 +74,26 @@ int CmdPurge::execute (std::string&) if (task.getStatus () == Task::deleted) { - context.tdb2.purge (task); - count++; + std::string question; + question = format (STRING_CMD_PURGE_CONFIRM, + task.identifier (true), + task.get ("description")); - // Remove dependencies on the task being purged - for (auto& blockedConst: context.tdb2.all_tasks ()) + if (permission (question, filtered.size ())) { - Task& blocked = const_cast(blockedConst); - if (blocked.has ("depends") && - blocked.get ("depends").find (uuid) != std::string::npos) + context.tdb2.purge (task); + count++; + + // Remove dependencies on the task being purged + for (auto& blockedConst: context.tdb2.all_tasks ()) { - blocked.removeDependency (uuid); - context.tdb2.modify (blocked); + Task& blocked = const_cast(blockedConst); + if (blocked.has ("depends") && + blocked.get ("depends").find (uuid) != std::string::npos) + { + blocked.removeDependency (uuid); + context.tdb2.modify (blocked); + } } } } diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 857628cf4..3bded4f9e 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -399,6 +399,7 @@ #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "Task not started." From b0336dfd505c7dde1f95b894b58083950a0940e0 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 15:16:05 +0100 Subject: [PATCH 0022/1455] CmdPurge: Move dependency handling into separate method --- src/commands/CmdPurge.cpp | 32 ++++++++++++++++++++------------ src/commands/CmdPurge.h | 2 ++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index 1d9143e43..ef9816e3e 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -51,6 +51,25 @@ CmdPurge::CmdPurge () _category = Command::Category::operation; } +//////////////////////////////////////////////////////////////////////////////// +// Makes sure that any task having the dependency on the task being purged +// has that dependency removed, to preserve referential integrity. +void CmdPurge::handleDeps (Task& task) +{ + std::string uuid = task.get ("uuid"); + + for (auto& blockedConst: context.tdb2.all_tasks ()) + { + Task& blocked = const_cast(blockedConst); + if (blocked.has ("depends") && + blocked.get ("depends").find (uuid) != std::string::npos) + { + blocked.removeDependency (uuid); + context.tdb2.modify (blocked); + } + } +} + //////////////////////////////////////////////////////////////////////////////// int CmdPurge::execute (std::string&) { @@ -82,19 +101,8 @@ int CmdPurge::execute (std::string&) if (permission (question, filtered.size ())) { context.tdb2.purge (task); + handleDeps(task); count++; - - // Remove dependencies on the task being purged - for (auto& blockedConst: context.tdb2.all_tasks ()) - { - Task& blocked = const_cast(blockedConst); - if (blocked.has ("depends") && - blocked.get ("depends").find (uuid) != std::string::npos) - { - blocked.removeDependency (uuid); - context.tdb2.modify (blocked); - } - } } } } diff --git a/src/commands/CmdPurge.h b/src/commands/CmdPurge.h index 8e9c76446..76644f3b3 100644 --- a/src/commands/CmdPurge.h +++ b/src/commands/CmdPurge.h @@ -32,6 +32,8 @@ class CmdPurge : public Command { +private: + void handleDeps (Task& task); public: CmdPurge (); int execute (std::string&); From 56a897511f5bd6b390f33ee5a7f7c90841fd4db6 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 15:45:15 +0100 Subject: [PATCH 0023/1455] CmdPurge: Simplify implementation --- src/commands/CmdPurge.cpp | 23 ++++++++++++++++------- src/commands/CmdPurge.h | 1 + 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index ef9816e3e..040598c19 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -51,6 +51,16 @@ CmdPurge::CmdPurge () _category = Command::Category::operation; } +//////////////////////////////////////////////////////////////////////////////// +// Purges the task, while taking care of: +// - dependencies on this task +void CmdPurge::purgeTask (Task& task, int& count) +{ + context.tdb2.purge (task); + handleDeps (task); + count++; +} + //////////////////////////////////////////////////////////////////////////////// // Makes sure that any task having the dependency on the task being purged // has that dependency removed, to preserve referential integrity. @@ -89,8 +99,11 @@ int CmdPurge::execute (std::string&) for (auto& task : filtered) { - std::string uuid = task.get ("uuid"); - + // Allow purging of deleted tasks only. Hence no need to deal with: + // - unblocked tasks notifications (deleted tasks are not blocking) + // - project changes (deleted tasks not included in progress) + // It also has the nice property of being explicit - users need to + // mark tasks as deleted before purging. if (task.getStatus () == Task::deleted) { std::string question; @@ -99,11 +112,7 @@ int CmdPurge::execute (std::string&) task.get ("description")); if (permission (question, filtered.size ())) - { - context.tdb2.purge (task); - handleDeps(task); - count++; - } + purgeTask (task, count); } } diff --git a/src/commands/CmdPurge.h b/src/commands/CmdPurge.h index 76644f3b3..7081e9776 100644 --- a/src/commands/CmdPurge.h +++ b/src/commands/CmdPurge.h @@ -33,6 +33,7 @@ class CmdPurge : public Command { private: + void purgeTask (Task& task, int& count); void handleDeps (Task& task); public: CmdPurge (); From 4465b48f75f1bbf9ed92e8169db89d6bb8c07ea9 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 15:46:17 +0100 Subject: [PATCH 0024/1455] TDB2: Fix wrong comment --- src/TDB2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TDB2.cpp b/src/TDB2.cpp index 5d501eb9b..0f3e696c3 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -1408,7 +1408,7 @@ const std::vector TDB2::children (Task& task) if (i.getStatus () != Task::completed && i.getStatus () != Task::deleted) { - // If task has the same parent, it is a sibling. + // If task has the given task as a parent, it is a child task. if (i.get ("parent") == parent) results.push_back (i); } From ec38b3afd8207a9a2a8f5ec8ef590db2ef151021 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 17:25:03 +0100 Subject: [PATCH 0025/1455] CmdPurge: Handle child tasks of recurrence templates --- src/commands/CmdPurge.cpp | 53 +++++++++++++++++++++++++++++++++++++++ src/commands/CmdPurge.h | 1 + src/l10n/eng-USA.h | 3 +++ 3 files changed, 57 insertions(+) diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index 040598c19..ab6d3b4b7 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -31,6 +31,7 @@ #include #include #include +#include extern Context context; @@ -54,10 +55,12 @@ CmdPurge::CmdPurge () //////////////////////////////////////////////////////////////////////////////// // Purges the task, while taking care of: // - dependencies on this task +// - child tasks void CmdPurge::purgeTask (Task& task, int& count) { context.tdb2.purge (task); handleDeps (task); + handleChildren (task, count); count++; } @@ -80,6 +83,56 @@ void CmdPurge::handleDeps (Task& task) } } +//////////////////////////////////////////////////////////////////////////////// +// Makes sure that with any recurrence parent are all the child tasks removed +// as well. If user chooses not to, the whole command is aborted. +void CmdPurge::handleChildren (Task& task, int& count) +{ + // If this is not a recurrence parent, we have no job here + if (!task.has ("mask")) + return; + + std::string uuid = task.get ("uuid"); + std::vector children; + + // Find all child tasks + for (auto& childConst: context.tdb2.all_tasks ()) + { + Task& child = const_cast (childConst); + + if (child.get ("parent") == uuid) + { + if (child.getStatus () != Task::deleted) + // In case any child task is not deleted, bail out + throw format (STRING_CMD_PURGE_NDEL_CHILD, + task.get ("description"), + child.identifier (true)); + else + children.push_back (child); + } + } + + // If there are no children, our job is done + if (children.empty ()) + return; + + // Ask for confirmation to purge them, if needed + std::string question = format (STRING_CMD_PURGE_CONFIRM_R, + task.get ("description"), + children.size ()); + + if (context.config.getBoolean ("recurrence.confirmation") || + (context.config.get ("recurrence.confirmation") == "prompt" + && confirm (question))) + { + for (auto& child: children) + purgeTask (child, count); + } + else + throw std::string (STRING_CMD_PURGE_ABRT); +} + + //////////////////////////////////////////////////////////////////////////////// int CmdPurge::execute (std::string&) { diff --git a/src/commands/CmdPurge.h b/src/commands/CmdPurge.h index 7081e9776..3bb0f2c82 100644 --- a/src/commands/CmdPurge.h +++ b/src/commands/CmdPurge.h @@ -34,6 +34,7 @@ class CmdPurge : public Command { private: void purgeTask (Task& task, int& count); + void handleChildren (Task& task, int& count); void handleDeps (Task& task); public: CmdPurge (); diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 3bded4f9e..84de21d6b 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -397,9 +397,12 @@ #define STRING_CMD_DUPLICATE_N "Duplicated {1} tasks." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." #define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "Task not started." From 4b5efe11368800589ae6a1ca337671fc5fdfcd5c Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 17:33:42 +0100 Subject: [PATCH 0026/1455] tests: The purge command now requires confirmation --- test/purge.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/purge.t b/test/purge.t index 7b8363683..cce3bf733 100755 --- a/test/purge.t +++ b/test/purge.t @@ -47,7 +47,7 @@ class TestDelete(TestCase): code, out, err = self.t("1 delete", input="y\n") self.assertIn("Deleted 1 task.", out) - code, out, err = self.t(uuid + " purge") + code, out, err = self.t(uuid + " purge", input="y\n") self.assertIn("Purged 1 task.", out) code, out, err = self.t("uuids") @@ -62,7 +62,7 @@ class TestDelete(TestCase): code, out, err = self.t("1 delete", input="y\n") self.assertIn("Deleted 1 task.", out) - code, out, err = self.t(uuid + " purge") + code, out, err = self.t(uuid + " purge", input="y\n") self.assertIn("Purged 1 task.", out) code, out, err = self.t("uuids") From 9a2a642014fae9ab93397c70f5577e1cb62d2b03 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 18:26:16 +0100 Subject: [PATCH 0027/1455] tests: Expand test cases for purge command --- test/purge.t | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/test/purge.t b/test/purge.t index cce3bf733..afa2ddd3c 100755 --- a/test/purge.t +++ b/test/purge.t @@ -54,7 +54,7 @@ class TestDelete(TestCase): self.assertNotIn(uuid, out) def test_purge_remove_deps(self): - """Verify that purge command removes dependency references""" + """Purge command removes broken dependency references""" self.t("add one") self.t("add two dep:1") uuid = self.t("_get 1.uuid")[1].strip() @@ -71,6 +71,86 @@ class TestDelete(TestCase): dependencies = self.t("_get 1.depends")[1].strip() self.assertNotIn(uuid, dependencies) + def test_purge_children(self): + """Purge command indirectly purges child tasks""" + self.t("add one recur:daily due:yesterday") + uuid = self.t("_get 1.uuid")[1].strip() + + # A dummy call to report, so that recurrence tasks get generated + self.t("list") + + code, out, err = self.t("1 delete", input="y\ny\n") + self.assertIn("Deleted 4 tasks.", out) + + code, out, err = self.t(uuid + " purge", input="y\ny\n") + self.assertIn("Purged 4 tasks.", out) + + code, out, err = self.t("uuids") + self.assertEqual('\n', out) + + def test_purge_children_fail_pending(self): + """Purge aborts if task has pending children""" + self.t("add one recur:daily due:yesterday") + uuid = self.t("_get 1.uuid")[1].strip() + + # A dummy call to report, so that recurrence tasks get generated + self.t("list") + + code, out, err = self.t("1 delete", input="y\nn\n") + self.assertIn("Deleted 1 task.", out) + + code, out, err = self.t.runError(uuid + " purge", input="y\n") + self.assertIn("child task 1 must be deleted before", err) + + # Check that nothing was purged + code, out, err = self.t("count") + self.assertEqual('4\n', out) + + def test_purge_children_fail_confirm(self): + """Purge aborts if user does not agree with it affecting child tasks""" + self.t("add one recur:daily due:yesterday") + uuid = self.t("_get 1.uuid")[1].strip() + + # A dummy call to report, so that recurrence tasks get generated + self.t("list") + + code, out, err = self.t("1 delete", input="y\ny\n") + self.assertIn("Deleted 4 tasks.", out) + + # Do not agree with purging of the child tasks + code, out, err = self.t.runError(uuid + " purge", input="y\nn\n") + self.assertIn("Purge operation aborted.", err) + + # Check that nothing was purged + code, out, err = self.t("count") + self.assertEqual('4\n', out) + + def test_purge_children(self): + """Purge command removes dependencies on indirectly purged tasks""" + self.t("add one recur:daily due:yesterday") + uuid = self.t("_get 1.uuid")[1].strip() + + # A dummy call to report, so that recurrence tasks get generated + self.t("list") + self.t("add two dep:4") + + # Check that the dependency is present + dependencies = self.t("_get 5.depends")[1].strip() + self.assertNotEqual("", dependencies) + + code, out, err = self.t("1 delete", input="y\ny\n") + self.assertIn("Deleted 4 tasks.", out) + + code, out, err = self.t(uuid + " purge", input="y\ny\n") + self.assertIn("Purged 4 tasks.", out) + + # Make sure we are dealing with the intended task + description = self.t("_get 1.description")[1].strip() + self.assertEqual("two", description) + + # Check that the dependency was removed + dependencies = self.t("_get 1.depends")[1].strip() + self.assertEqual("", dependencies) if __name__ == "__main__": from simpletap import TAPTestRunner From 9a29417bb53e4e93f323b800d0593a6add3f710b Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 19:21:07 +0100 Subject: [PATCH 0028/1455] docs: Document new purge command --- doc/man/task.1.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/man/task.1.in b/doc/man/task.1.in index 684143e74..d6f8d2f51 100644 --- a/doc/man/task.1.in +++ b/doc/man/task.1.in @@ -376,6 +376,14 @@ Modifies the existing task with provided information. .B task prepend Prepends description text to an existing task. +.TP +.B task purge +Permanently removes the specified tasks from the data files. Only +tasks that are alredy deleted can be purged. This command has a +local-only effect and changes introduced by it are not synced. + +Warning: causes permanent, non-revertible loss of data. + .TP .B task start Marks the specified tasks as started. From 6e2a9c791f269de34b5f414fe128b48eba6d05ee Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 19:24:44 +0100 Subject: [PATCH 0029/1455] docs: Update ChangeLog and NEWS --- ChangeLog | 6 ++++-- NEWS | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6d03e9694..57892d6df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,9 @@ 2.6.0 () - -- TD-64 sync conflict deleted all annotations of the task - (thanks to Markus Beppler, Konstantin Vorobyev). +- TD-64 sync conflict deleted all annotations of the task + (thanks to Markus Beppler, Konstantin Vorobyev). +- TW-1785 Purge command to remove deleted tasks + (thanks to Paul Beckingham) - Removed deprecated 'alias._query' setting. ------ current release --------------------------- diff --git a/NEWS b/NEWS index df4002e1c..91debe2dc 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,7 @@ New Features in Taskwarrior 2.6.0 New Commands in Taskwarrior 2.6.0 - - + - The 'purge' command was introduced. New Configuration Options in Taskwarrior 2.6.0 From 58a0e9c2e443bc1d62ad3758c818c5ac907f401a Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 19:28:09 +0100 Subject: [PATCH 0030/1455] l10n: Propagate the purge-related strings into language files --- src/l10n/deu-DEU.h | 4 ++++ src/l10n/epo-RUS.h | 4 ++++ src/l10n/esp-ESP.h | 4 ++++ src/l10n/fra-FRA.h | 4 ++++ src/l10n/ita-ITA.h | 4 ++++ src/l10n/jpn-JPN.h | 4 ++++ src/l10n/pol-POL.h | 4 ++++ src/l10n/por-PRT.h | 4 ++++ 8 files changed, 32 insertions(+) diff --git a/src/l10n/deu-DEU.h b/src/l10n/deu-DEU.h index e3b4a003c..3135d37ac 100644 --- a/src/l10n/deu-DEU.h +++ b/src/l10n/deu-DEU.h @@ -399,8 +399,12 @@ #define STRING_CMD_DUPLICATE_N "{1} Aufgaben verdoppelt." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Kennzeichnet die gewählte Aufgabe als begonnen." #define STRING_CMD_START_NO "Aufgabe nicht begonnen." diff --git a/src/l10n/epo-RUS.h b/src/l10n/epo-RUS.h index 1412ce5b9..cb07b51e7 100644 --- a/src/l10n/epo-RUS.h +++ b/src/l10n/epo-RUS.h @@ -399,8 +399,12 @@ #define STRING_CMD_DUPLICATE_N "Kopiis {1} taskojn." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Markas la specifatan taskon kiel ekita" #define STRING_CMD_START_NO "Ne ekis taskon." diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index 15e3f638d..4ca54b673 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -404,8 +404,12 @@ #define STRING_CMD_DUPLICATE_N "Duplicadas {1} tareas." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Marca la tarea especificada como comenzada" #define STRING_CMD_START_NO "Tarea no comenzada." diff --git a/src/l10n/fra-FRA.h b/src/l10n/fra-FRA.h index 8ca0a4f0e..4046ed457 100644 --- a/src/l10n/fra-FRA.h +++ b/src/l10n/fra-FRA.h @@ -399,8 +399,12 @@ #define STRING_CMD_DUPLICATE_N "Duplicated {1} tasks." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "Tâche non démarrée." diff --git a/src/l10n/ita-ITA.h b/src/l10n/ita-ITA.h index f5a6e48ac..95e0da6b2 100644 --- a/src/l10n/ita-ITA.h +++ b/src/l10n/ita-ITA.h @@ -398,8 +398,12 @@ #define STRING_CMD_DUPLICATE_N "Task {1} duplicati." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Contrassegna i task specificati come avviati" #define STRING_CMD_START_NO "Task non avviato." diff --git a/src/l10n/jpn-JPN.h b/src/l10n/jpn-JPN.h index a6d8b0c7b..e82ba9bc7 100644 --- a/src/l10n/jpn-JPN.h +++ b/src/l10n/jpn-JPN.h @@ -399,8 +399,12 @@ #define STRING_CMD_DUPLICATE_N "重複した {1} タスク。" #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "タスク は開始していません。" diff --git a/src/l10n/pol-POL.h b/src/l10n/pol-POL.h index 529599321..1264c3f6f 100644 --- a/src/l10n/pol-POL.h +++ b/src/l10n/pol-POL.h @@ -399,8 +399,12 @@ #define STRING_CMD_DUPLICATE_N "Skopiowano {1} zadań." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Oznacza zadanie jako uruchomione" #define STRING_CMD_START_NO "Zadanie nie uruchomione" diff --git a/src/l10n/por-PRT.h b/src/l10n/por-PRT.h index f310a6d2d..0de68ed5c 100644 --- a/src/l10n/por-PRT.h +++ b/src/l10n/por-PRT.h @@ -399,8 +399,12 @@ #define STRING_CMD_DUPLICATE_N "Duplicadas {1} tarefas." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." +#define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Assinala a tarefa especificada como iniciada" #define STRING_CMD_START_NO "Tarefa não iniciada." From 10018dac18eaee12ab83ffc3a9107b0d9c50b54d Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Tue, 22 Mar 2016 02:49:01 +0100 Subject: [PATCH 0031/1455] dependencyIsCircular: Do not visit one node multiple times --- src/dependency.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/dependency.cpp b/src/dependency.cpp index 608f0b5bc..124610d6f 100644 --- a/src/dependency.cpp +++ b/src/dependency.cpp @@ -75,7 +75,11 @@ bool dependencyIsCircular (const Task& task) auto task_uuid = task.get ("uuid"); std::stack s; + std::unordered_set visited; + s.push (task); + visited.insert (task_uuid); + while (! s.empty ()) { Task& current = s.top (); @@ -83,21 +87,25 @@ bool dependencyIsCircular (const Task& task) current.getDependencies (deps_current); // This is a basic depth first search that always terminates given the - // assumption that any cycles in the dependency graph must have been - // introduced by the task that is being checked. - // Since any previous cycles would have been prevented by this very - // function, this is a reasonable assumption. + // fact that we do not visit any task twice for (unsigned int i = 0; i < deps_current.size (); i++) { if (context.tdb2.get (deps_current[i], current)) { - if (task_uuid == current.get ("uuid")) + auto current_uuid = current.get ("uuid"); + + if (task_uuid == current_uuid) { // Cycle found, initial task reached for the second time! return true; } - s.push (current); + if (visited.find (current_uuid) == visited.end ()) + { + // Push the task to the stack, if it has not been processed yet + s.push (current); + visited.insert (current_uuid); + } } } From 727602f26f8aac8527f8a0ba096fa1284ffd3653 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Tue, 22 Mar 2016 02:50:48 +0100 Subject: [PATCH 0032/1455] TW-1772: Implementation of circular dependency detection is inefficient - Thanks to Michael Meier. --- AUTHORS | 1 + ChangeLog | 2 ++ 2 files changed, 3 insertions(+) diff --git a/AUTHORS b/AUTHORS index 1e2e01e2c..2f2743f28 100644 --- a/AUTHORS +++ b/AUTHORS @@ -288,3 +288,4 @@ suggestions: pawprint Reg Yaroslav Molochko + Michael Meier diff --git a/ChangeLog b/ChangeLog index 57892d6df..9b5bddf5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,8 @@ (thanks to Markus Beppler, Konstantin Vorobyev). - TW-1785 Purge command to remove deleted tasks (thanks to Paul Beckingham) +- TW-1772 Implementation of circular dependency detection is + inefficient (thanks to Michael Meier). - Removed deprecated 'alias._query' setting. ------ current release --------------------------- From cc324fdb8d6aeb5029921abb9e65ff90d5c9cc58 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Tue, 22 Mar 2016 23:42:23 +0100 Subject: [PATCH 0033/1455] validate: Pending tasks cannot have end attribute set --- src/Task.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Task.cpp b/src/Task.cpp index 23e3a44a5..6ac7c952c 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -1491,6 +1491,10 @@ void Task::validate (bool applyDefault /* = true */) (! has ("end") || get ("end") == "")) setAsNow ("end"); + // Pending tasks cannot have an end date, remove if present + if ((status == Task::pending) && (get ("end") != "")) + remove ("end"); + // Provide an entry date unless user already specified one. if (! has ("modified") || get ("modified") == "") setAsNow ("modified"); From fe58b42f68118ccc90fcdca7bc912bde0b57ab1b Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Tue, 22 Mar 2016 23:43:27 +0100 Subject: [PATCH 0034/1455] tests: Add test for TW-1788 --- test/start.t | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/start.t b/test/start.t index a1d143864..63befe283 100755 --- a/test/start.t +++ b/test/start.t @@ -95,6 +95,19 @@ class TestStart(TestCase): code, out, err = self.t("long") self.assertIn("Nu stannar vi", out) + def test_start_remove_end(self): + """Verify that starting a task removes end timestamp""" + self.t("add one") + uuid = self.t('_get 1.uuid')[1].strip() + + self.t("1 done") + task = self.t.export()[0] + self.assertIn("end", task) + + self.t(uuid + " start") + task = self.t.export()[0] + self.assertNotIn("end", task) + class TestActiveTaskHandling(TestCase): def setUp(self): From 76d9ed2148a3fa681b069344236fb7a3483f790d Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Tue, 22 Mar 2016 23:43:49 +0100 Subject: [PATCH 0035/1455] TW-1788: Closing a reopened task does not update the end time - Thanks to Ralph Bean. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9b5bddf5e..b491a1f5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,8 @@ (thanks to Paul Beckingham) - TW-1772 Implementation of circular dependency detection is inefficient (thanks to Michael Meier). +- TW-1788 Closing a reopened task does not update the end time (thanks + to Ralph Bean). - Removed deprecated 'alias._query' setting. ------ current release --------------------------- From 68cde6aa7e647688ac66b57a980933a55f431ad2 Mon Sep 17 00:00:00 2001 From: Tom Sydney Kerckhove Date: Sat, 26 Mar 2016 15:30:02 +0100 Subject: [PATCH 0036/1455] Docs: fixed inconsistency in the spelling of CMake --- AUTHORS | 1 + INSTALL | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 2f2743f28..3cb2e526a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -127,6 +127,7 @@ The following submitted code, packages or analysis, and deserve special thanks: Misty De Meo Kent R. Spillner Konstantin Vorobyev + Tom Sydney Kerckhove Thanks to the following, who submitted detailed bug reports and excellent suggestions: diff --git a/INSTALL b/INSTALL index 034caee9a..1c6a5e862 100644 --- a/INSTALL +++ b/INSTALL @@ -9,7 +9,7 @@ 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 +from source. More information on CMake can be obtained at http://cmake.org You will also need: - make From 325771d8998fb73f9b78b835743850132b3888ce Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 26 Mar 2016 21:21:51 -0400 Subject: [PATCH 0037/1455] Tests: Typo in test --- test/version.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/version.t b/test/version.t index 5880ee5c2..76e8a2f58 100755 --- a/test/version.t +++ b/test/version.t @@ -110,7 +110,7 @@ class TestVersion(TestCase): self.assertIn(expected, out) def test_version_option(self): - """Verify that 'task --version' returnes something valid""" + """Verify that 'task --version' returns something valid""" code, out, err = self.t("--version") self.assertRegexpMatches(out, r'^\d\.\d+\.\d+(\.\w+)?$') From 6a790e3675e0b14fd622da97b81ca8682c338220 Mon Sep 17 00:00:00 2001 From: Lynoure Braakman Date: Sun, 27 Mar 2016 22:34:57 +0200 Subject: [PATCH 0038/1455] juhannus as an alternative name for midsommarafton --- AUTHORS | 1 + ChangeLog | 6 ++++-- doc/man/task.1.in | 2 ++ src/Dates.cpp | 5 +++-- test/dates.t.cpp | 2 ++ 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 3cb2e526a..681ec89e5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -128,6 +128,7 @@ The following submitted code, packages or analysis, and deserve special thanks: Kent R. Spillner Konstantin Vorobyev Tom Sydney Kerckhove + Lynoure Braakman Thanks to the following, who submitted detailed bug reports and excellent suggestions: diff --git a/ChangeLog b/ChangeLog index b491a1f5a..8667161eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,8 +6,10 @@ (thanks to Paul Beckingham) - TW-1772 Implementation of circular dependency detection is inefficient (thanks to Michael Meier). -- TW-1788 Closing a reopened task does not update the end time (thanks - to Ralph Bean). +- TW-1788 Closing a reopened task does not update the end time + (thanks to Ralph Bean). +- Added 'juhannus' as a synonym for 'midsommarafton' + (thanks to Lynoure Braakman). - Removed deprecated 'alias._query' setting. ------ current release --------------------------- diff --git a/doc/man/task.1.in b/doc/man/task.1.in index d6f8d2f51..3a9670b91 100644 --- a/doc/man/task.1.in +++ b/doc/man/task.1.in @@ -1048,6 +1048,8 @@ task ... due:pentecost task ... due:midsommar .br task ... due:midsommarafton +.br +task ... due:juhannus .RE .SS FREQUENCIES diff --git a/src/Dates.cpp b/src/Dates.cpp index a0b5035c2..a721b6a49 100644 --- a/src/Dates.cpp +++ b/src/Dates.cpp @@ -93,7 +93,7 @@ static void midsommar (struct tm* t) static void midsommarafton (struct tm* t) { t->tm_mon = 5; // June. - t->tm_mday = 19; // Saturday after 20th. + t->tm_mday = 19; // Friday after 19th. t->tm_hour = t->tm_min = t->tm_sec = 0; // Midnight. t->tm_isdst = -1; // Probably DST, but check. @@ -491,7 +491,8 @@ bool namedDates (const std::string& name, Variant& value) value = Variant (mktime (t), Variant::type_date); } - else if (closeEnough ("midsommarafton", name, minimum)) + else if (closeEnough ("midsommarafton", name, minimum) || + closeEnough ("juhannus", name, minimum)) { Variant valueNow = Variant (mktime (t), Variant::type_date); midsommarafton (t); diff --git a/test/dates.t.cpp b/test/dates.t.cpp index 0b1b9edc3..1075a0178 100644 --- a/test/dates.t.cpp +++ b/test/dates.t.cpp @@ -146,6 +146,7 @@ int main (int, char**) Variant var_false; testInit (t, "false", var_false); Variant midsommar; testInit (t, "midsommar", midsommar); Variant midsommarafton; testInit (t, "midsommarafton", midsommarafton); + Variant juhannus; testInit (t, "juhannus", juhannus); Variant first; testInit (t, "1st", first); Variant second; testInit (t, "2nd", second); Variant third; testInit (t, "3rd", third); @@ -173,6 +174,7 @@ int main (int, char**) t.ok (easter < eastermonday, "easter < eastermonday"); t.ok (easter < midsommarafton, "easter < midsommarafton"); t.ok (midsommarafton < midsommar, "midsommarafton < midsommar"); + t.ok (juhannus == midsommarafton, "juhannus == midsommarafton"); return 0; } From b2d49f3973e3c43b4fc5b4b5e4516b0bed9f54f1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 29 Mar 2016 07:52:38 -0400 Subject: [PATCH 0039/1455] Task: Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' virtual tag. - Thanks to Tomas Babej --- ChangeLog | 2 ++ NEWS | 3 ++- doc/man/task.1.in | 1 - src/Task.cpp | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8667161eb..5a1630b62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,8 @@ (thanks to Ralph Bean). - Added 'juhannus' as a synonym for 'midsommarafton' (thanks to Lynoure Braakman). +- Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' + virtual tag. - Removed deprecated 'alias._query' setting. ------ current release --------------------------- diff --git a/NEWS b/NEWS index 91debe2dc..84f42d004 100644 --- a/NEWS +++ b/NEWS @@ -13,7 +13,8 @@ New Configuration Options in Taskwarrior 2.6.0 Newly Deprecated Features in Taskwarrior 2.6.0 - - + - The 'DUETODAY' virtual tag is a synonym for the 'TODAY' virtual tag, and is + not needed. Removed Features in 2.6.0 diff --git a/doc/man/task.1.in b/doc/man/task.1.in index 3a9670b91..ac6707c6e 100644 --- a/doc/man/task.1.in +++ b/doc/man/task.1.in @@ -682,7 +682,6 @@ are: 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 LATEST Matches if the task is the newest added task MONTH Matches if the task is due this month ORPHAN Matches if the task has any orphaned UDA values diff --git a/src/Task.cpp b/src/Task.cpp index 6ac7c952c..884e7f23e 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -1212,7 +1212,7 @@ bool Task::hasTag (const std::string& tag) const #ifdef PRODUCT_TASKWARRIOR if (tag == "READY") return is_ready (); if (tag == "DUE") return is_due (); - if (tag == "DUETODAY") return is_duetoday (); + if (tag == "DUETODAY") return is_duetoday (); // 2016-03-29: Deprecated in 2.6.0 if (tag == "TODAY") return is_duetoday (); if (tag == "YESTERDAY") return is_dueyesterday (); if (tag == "TOMORROW") return is_duetomorrow (); From f91df9c9723d93f435a5ac2bbc2ad2e4eaacc652 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 29 Mar 2016 22:56:07 -0400 Subject: [PATCH 0040/1455] Tests: Updated test harness --- test/test.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test.cpp b/test/test.cpp index de1e9f1d2..60ddd3cf5 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -416,7 +416,9 @@ void UnitTest::diag (const std::string& text) { auto start = text.find_first_not_of (" \t\n\r\f"); auto end = text.find_last_not_of (" \t\n\r\f"); - std::cout << "# " << text.substr (start, end - start + 1) << "\n"; + if (start != std::string::npos && + end != std::string::npos) + std::cout << "# " << text.substr (start, end - start + 1) << "\n"; } /////////////////////////////////////////////////////////////////////////////// From 6f819af367f640ab7dcda568a50e9eefbd7df907 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 2 Apr 2016 15:08:35 -0400 Subject: [PATCH 0041/1455] TW-1791: taskrc(5) manpage: spurious "pri." in rule.precedence.color - Thanks to Sebastien Badia. --- AUTHORS | 2 +- ChangeLog | 2 ++ doc/man/taskrc.5.in | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 681ec89e5..24b3f475a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -129,6 +129,7 @@ The following submitted code, packages or analysis, and deserve special thanks: Konstantin Vorobyev Tom Sydney Kerckhove Lynoure Braakman + Sebastien Badia Thanks to the following, who submitted detailed bug reports and excellent suggestions: @@ -276,7 +277,6 @@ suggestions: James Cline Ryan Simon W. Jackson - Sebastien Badia Michale Meier Svetoslav Trochev Marc Cornellà diff --git a/ChangeLog b/ChangeLog index 5a1630b62..eae2dfa0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,8 @@ inefficient (thanks to Michael Meier). - TW-1788 Closing a reopened task does not update the end time (thanks to Ralph Bean). +- TW-1791 taskrc(5) manpage: spurious "pri." in rule.precedence.color + (thanks to Sebastien Badia). - Added 'juhannus' as a synonym for 'midsommarafton' (thanks to Lynoure Braakman). - Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' diff --git a/doc/man/taskrc.5.in b/doc/man/taskrc.5.in index 2de7799bf..83294dd83 100644 --- a/doc/man/taskrc.5.in +++ b/doc/man/taskrc.5.in @@ -1056,7 +1056,7 @@ Colors the output of the sync command. .TP .B rule.precedence.color=due.today,active,blocking,blocked,overdue,due, .B scheduled,keyword.,project.,tag.,uda.,recurring, -.B pri.,tagged,completed,deleted +.B tagged,completed,deleted .RS This setting specifies the precedence of the color rules, from highest to lowest. Note that the prefix 'color.' is omitted (for brevity), and that any From f3147a512cdc2d664db09dd4f1772ffb92cb832b Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 3 Apr 2016 11:05:32 +0200 Subject: [PATCH 0042/1455] feedback: Use task identifiers instead of IDs During construction of a feedback string for a dependency change, a list of IDs of the dependencies was used. However, if the tasks being referred to are already deleted / completed, their respective IDs are all 0s. Use shortened UUIDs in such case. --- src/Task.cpp | 16 ++++++++++++++++ src/Task.h | 1 + src/feedback.cpp | 50 +++++++++++++++++++++++++++--------------------- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/Task.cpp b/src/Task.cpp index 884e7f23e..d53f8a540 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -1177,6 +1177,22 @@ void Task::getDependencies (std::vector & all) const all.clear (); split (all, get ("depends"), ','); } + +//////////////////////////////////////////////////////////////////////////////// +void Task::getDependencies (std::vector & all) const +{ + std::vector deps; + split (deps, get ("depends"), ','); + + all.clear (); + + for (auto& dep : deps) + { + Task task; + context.tdb2.get (dep, task); + all.push_back (task); + } +} #endif //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Task.h b/src/Task.h index 47245b588..474049179 100644 --- a/src/Task.h +++ b/src/Task.h @@ -142,6 +142,7 @@ public: void removeDependency (const std::string&); void getDependencies (std::vector &) const; void getDependencies (std::vector &) const; + void getDependencies (std::vector &) const; void getUDAOrphans (std::vector &) const; diff --git a/src/feedback.cpp b/src/feedback.cpp index 213eb3b09..49f5a4556 100644 --- a/src/feedback.cpp +++ b/src/feedback.cpp @@ -44,6 +44,20 @@ extern Context context; static void countTasks (const std::vector &, const std::string&, int&, int&); +//////////////////////////////////////////////////////////////////////////////// +// Converts a vector of tasks to a human-readable string that represents the tasks. +std::string taskIdentifiers (const std::vector & tasks) +{ + std::vector identifiers; + for (auto task: tasks) + identifiers.push_back (task.identifier (true)); + + std::string result; + join (result, ", ", identifiers); + + return result; +} + //////////////////////////////////////////////////////////////////////////////// std::string taskDifferences (const Task& before, const Task& after) { @@ -72,13 +86,11 @@ std::string taskDifferences (const Task& before, const Task& after) { if (name == "depends") { - std::vector deps_after; + std::vector deps_after; after.getDependencies (deps_after); - std::string to; - join (to, ", ", deps_after); out << " - " - << format (STRING_FEEDBACK_DEP_SET, to) + << format (STRING_FEEDBACK_DEP_SET, taskIdentifiers (deps_after)) << "\n"; } else @@ -100,15 +112,13 @@ std::string taskDifferences (const Task& before, const Task& after) { if (name == "depends") { - std::vector deps_before; + std::vector deps_before; before.getDependencies (deps_before); - std::string from; - join (from, ", ", deps_before); + std::string from = taskIdentifiers (deps_before); - std::vector deps_after; + std::vector deps_after; after.getDependencies (deps_after); - std::string to; - join (to, ", ", deps_after); + std::string to = taskIdentifiers (deps_after); out << " - " << format (STRING_FEEDBACK_DEP_MOD, from, to) @@ -161,10 +171,9 @@ std::string taskInfoDifferences ( { if (name == "depends") { - std::vector deps_before; + std::vector deps_before; before.getDependencies (deps_before); - std::string from; - join (from, ", ", deps_before); + std::string from = taskIdentifiers (deps_before); out << format (STRING_FEEDBACK_DEP_DEL, from) << "\n"; @@ -191,10 +200,9 @@ std::string taskInfoDifferences ( { if (name == "depends") { - std::vector deps_after; + std::vector deps_after; after.getDependencies (deps_after); - std::string to; - join (to, ", ", deps_after); + std::string to = taskIdentifiers (deps_after); out << format (STRING_FEEDBACK_DEP_WAS_SET, to) << "\n"; @@ -225,15 +233,13 @@ std::string taskInfoDifferences ( { if (name == "depends") { - std::vector deps_before; + std::vector deps_before; before.getDependencies (deps_before); - std::string from; - join (from, ", ", deps_before); + std::string from = taskIdentifiers (deps_before); - std::vector deps_after; + std::vector deps_after; after.getDependencies (deps_after); - std::string to; - join (to, ", ", deps_after); + std::string to = taskIdentifiers (deps_after); out << format (STRING_FEEDBACK_DEP_WAS_MOD, from, to) << "\n"; From 3d1498240ced8a496d766bf1c607066f9247f627 Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 3 Apr 2016 19:28:21 +0200 Subject: [PATCH 0043/1455] TW-1792: The info command uses '0' to reference dependencies on non-pending tasks - Thanks to Paul Beckingham for providing screenshots capturing the bug. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index eae2dfa0c..a7fce9099 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,8 @@ (thanks to Ralph Bean). - TW-1791 taskrc(5) manpage: spurious "pri." in rule.precedence.color (thanks to Sebastien Badia). +- TW-1792 The info command uses '0' to reference dependencies on non- + pending tasks. - Added 'juhannus' as a synonym for 'midsommarafton' (thanks to Lynoure Braakman). - Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' From 7232d79e67acc2da2fe831a8fa4997288522dba8 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 9 Apr 2016 16:18:07 -0400 Subject: [PATCH 0044/1455] cmake: Use the CXXSniffer --- CMakeLists.txt | 90 +++++++----------------------------------- cmake/CXXSniffer.cmake | 51 ++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 76 deletions(-) create mode 100644 cmake/CXXSniffer.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a17d09cb..4bf785e89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required (VERSION 2.8) set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") include (CheckFunctionExists) include (CheckStructHasMember) @@ -7,6 +8,8 @@ include (CheckStructHasMember) set (HAVE_CMAKE true) project (task) +include (CXXSniffer) + set (PROJECT_VERSION "2.6.0") OPTION (ENABLE_SYNC "Enable 'task sync' support" ON) @@ -18,82 +21,6 @@ else (ENABLE_SYNC) message (WARNING "ENABLE_SYNC=OFF. Not building sync support.") endif (ENABLE_SYNC) -message ("CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}") - -include (CheckCXXCompilerFlag) - -# NOTE: If we are to actually use C++11 features, we should either require -# a compiler that supports the -std=c++11 flag or check for the -# features used. -# Relying on -std=c++0x or even -std=gnu++0x is highly volatile. - -CHECK_CXX_COMPILER_FLAG("-std=c++11" _HAS_CXX11) -CHECK_CXX_COMPILER_FLAG("-std=c++0x" _HAS_CXX0X) -CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" _HAS_GNU0X) - -if (_HAS_CXX11) - set (_CXX11_FLAGS "-std=c++11") -elseif (_HAS_CXX0X) - message (WARNING "Enabling -std=c++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.") - set (_CXX11_FLAGS "-std=c++0x") -elseif (_HAS_GNU0X) - message (WARNING "Enabling -std=gnu++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.") - set (_CXX11_FLAGS "-std=gnu++0x") -else (_HAS_CXX11) - message (FATAL_ERROR "C++11 support missing. Try upgrading your C++ compiler. If you have a good reason for using an outdated compiler, please let us know at support@taskwarrior.org.") -endif (_HAS_CXX11) - -if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - set (_CXX11_FLAGS "${_CXX11_FLAGS} -stdlib=libc++") -endif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - -if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set (LINUX true) -elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set (DARWIN true) -elseif (${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD") - set (KFREEBSD true) -elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - set (FREEBSD true) -elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") - set (OPENBSD true) -elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD") - set (NETBSD true) -elseif (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") - set (SOLARIS true) -elseif (${CMAKE_SYSTEM_NAME} STREQUAL "GNU") - set (GNUHURD true) -elseif (${CMAKE_SYSTEM_NAME} STREQUAL "CYGWIN") - set (CYGWIN true) - # NOTE: Not setting -std=gnu++0x leads to compile errors even with - # GCC 4.8.3, and debugging those leads to insanity. Adding this - # workaround instead of fixing Cygwin. - set (_CXX11_FLAGS "-std=gnu++0x") -else (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set (UNKNOWN true) -endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - -set (CMAKE_CXX_FLAGS "${_CXX11_FLAGS} ${CMAKE_CXX_FLAGS}") - -set (CMAKE_CXX_FLAGS "-Wall -Wsign-compare -Wreturn-type ${CMAKE_CXX_FLAGS}") - -if (NETBSD) - # Since readline, etc likely to be in /usr/pkg/lib, not standard library - # Otherwise will remove links during install - set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -endif (NETBSD) - -if (FREEBSD) -SET (TASK_MAN1DIR man/man1 CACHE STRING "Installation directory for man pages, section 1") -SET (TASK_MAN5DIR man/man5 CACHE STRING "Installation directory for man pages, section 5") -else (FREEBSD) -SET (TASK_MAN1DIR share/man/man1 CACHE STRING "Installation directory for man pages, section 1") -SET (TASK_MAN5DIR share/man/man5 CACHE STRING "Installation directory for man pages, section 5") -endif (FREEBSD) -SET (TASK_DOCDIR share/doc/task CACHE STRING "Installation directory for doc files") -SET (TASK_RCDIR "${TASK_DOCDIR}/rc" CACHE STRING "Installation directory for configuration files") -SET (TASK_BINDIR bin CACHE STRING "Installation directory for the binary") - message ("-- Looking for SHA1 references") if (EXISTS ${CMAKE_SOURCE_DIR}/.git/index) set (HAVE_COMMIT true) @@ -113,6 +40,17 @@ set (PACKAGE_TARNAME "${PACKAGE}") set (PACKAGE_VERSION "${VERSION}") set (PACKAGE_STRING "${PACKAGE} ${VERSION}") +if (FREEBSD) +SET (TASK_MAN1DIR man/man1 CACHE STRING "Installation directory for man pages, section 1") +SET (TASK_MAN5DIR man/man5 CACHE STRING "Installation directory for man pages, section 5") +else (FREEBSD) +SET (TASK_MAN1DIR share/man/man1 CACHE STRING "Installation directory for man pages, section 1") +SET (TASK_MAN5DIR share/man/man5 CACHE STRING "Installation directory for man pages, section 5") +endif (FREEBSD) +SET (TASK_DOCDIR share/doc/task CACHE STRING "Installation directory for doc files") +SET (TASK_RCDIR "${TASK_DOCDIR}/rc" CACHE STRING "Installation directory for configuration files") +SET (TASK_BINDIR bin CACHE STRING "Installation directory for the binary") + if (USE_GNUTLS) message ("-- Looking for GnuTLS") find_package (GnuTLS) diff --git a/cmake/CXXSniffer.cmake b/cmake/CXXSniffer.cmake new file mode 100644 index 000000000..96062263b --- /dev/null +++ b/cmake/CXXSniffer.cmake @@ -0,0 +1,51 @@ +message ("-- Configuring C++11") +message ("-- System: ${CMAKE_SYSTEM_NAME}") + +include (CheckCXXCompilerFlag) + +# NOTE: Phase out -std=gnu++0x and --std=c++0x as soon as realistically possible. +CHECK_CXX_COMPILER_FLAG("-std=c++11" _HAS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" _HAS_CXX0X) +CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" _HAS_GNU0X) + +if (_HAS_CXX11) + set (_CXX11_FLAGS "-std=c++11") +elseif (_HAS_CXX0X) + message (WARNING "Enabling -std=c++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.") + set (_CXX11_FLAGS "-std=c++0x") +elseif (_HAS_GNU0X) + message (WARNING "Enabling -std=gnu++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.") + set (_CXX11_FLAGS "-std=gnu++0x") +else (_HAS_CXX11) + message (FATAL_ERROR "C++11 support missing. Try upgrading your C++ compiler. If you have a good reason for using an outdated compiler, please let us know at support@taskwarrior.org.") +endif (_HAS_CXX11) + +if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set (LINUX true) +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set (DARWIN true) + set (_CXX11_FLAGS "${_CXX11_FLAGS} -stdlib=libc++") +elseif (${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD") + set (KFREEBSD true) +elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + set (FREEBSD true) +elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") + set (OPENBSD true) +elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD") + set (NETBSD true) +elseif (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + set (SOLARIS true) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "GNU") + set (GNUHURD true) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "CYGWIN") + set (CYGWIN true) + # NOTE: Not setting -std=gnu++0x leads to compile errors even with + # GCC 4.8.3, and debugging those leads to insanity. Adding this + # workaround instead of fixing Cygwin. + set (_CXX11_FLAGS "-std=gnu++0x") +else (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set (UNKNOWN true) +endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + +set (CMAKE_CXX_FLAGS "${_CXX11_FLAGS} ${CMAKE_CXX_FLAGS}") +set (CMAKE_CXX_FLAGS "-Wall -Wextra -Wsign-compare -Wreturn-type ${CMAKE_CXX_FLAGS}") From 2800e473cb62321055e9fa22cc91052fb6ff9c42 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 9 Apr 2016 16:18:35 -0400 Subject: [PATCH 0045/1455] Tests: Wrong test count causes unexpected 'green' in test results --- test/dates.t.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dates.t.cpp b/test/dates.t.cpp index 1075a0178..9a73bdba3 100644 --- a/test/dates.t.cpp +++ b/test/dates.t.cpp @@ -55,7 +55,7 @@ void testInit (UnitTest& t, const std::string& value, Variant& var) //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { - UnitTest t (104); + UnitTest t (106); Variant sunday; testInit (t, "sunday", sunday); Variant monday; testInit (t, "monday", monday); From 7910a3cb5a95fd000743718f07cac0e3d0f5ede9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 13 Apr 2016 16:35:08 -0400 Subject: [PATCH 0046/1455] CMake: Added snotty comment about CMake bullshit --- test/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9cb997f31..411b61571 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,11 @@ cmake_minimum_required (VERSION 2.8) + +# See this CMake issue before complaining about the following. +# https://cmake.org/Bug/view.php?id=16062 if(POLICY CMP0037) cmake_policy(SET CMP0037 OLD) endif() + include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/commands From 1625dd6f10156d3aea6b3144cb5eda5347e94d47 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 15 Apr 2016 07:55:21 -0400 Subject: [PATCH 0047/1455] TW-1795: Calendar underline on Day padding - Thanks to Renato Alves. --- ChangeLog | 2 ++ src/commands/CmdCalendar.cpp | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7fce9099..51e851e1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,8 @@ (thanks to Sebastien Badia). - TW-1792 The info command uses '0' to reference dependencies on non- pending tasks. +- TW-1795 Calendar underline on Day padding + (thanks to Renato Alves). - Added 'juhannus' as a synonym for 'midsommarafton' (thanks to Lynoure Braakman). - Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' diff --git a/src/commands/CmdCalendar.cpp b/src/commands/CmdCalendar.cpp index 8a3c6cae5..36a9823ad 100644 --- a/src/commands/CmdCalendar.cpp +++ b/src/commands/CmdCalendar.cpp @@ -440,7 +440,7 @@ std::string CmdCalendar::renderMonths ( { if (weekStart == 1) { - view.add (Column::factory ("string.right", " ")); + view.add (Column::factory ("string.right", "")); 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))); @@ -451,7 +451,7 @@ std::string CmdCalendar::renderMonths ( } else { - view.add (Column::factory ("string.right", " ")); + view.add (Column::factory ("string.right", "")); 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))); @@ -516,7 +516,11 @@ std::string CmdCalendar::renderMonths ( int woy = temp.weekOfYear (weekStart); if (context.config.getBoolean ("displayweeknumber")) - view.set (row, (8 * mpl), woy, color_weeknumber); + view.set (row, + (8 * mpl), + // Make sure the week number is always 4 columns, space-padded. + format ((woy < 10 ? " {1}" : " {1}"), woy), + color_weeknumber); // Calculate column id. int thisCol = dow + // 0 = Sunday From a3cc616151354a2266433001e59ea107afef15fd Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 15 Apr 2016 08:06:17 -0400 Subject: [PATCH 0048/1455] Tests: Removed broken test - It was not only broken between easter and midsommarafton, but just performing an additional comparison. Not needed. --- test/dates.t.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/dates.t.cpp b/test/dates.t.cpp index 9a73bdba3..044e892a9 100644 --- a/test/dates.t.cpp +++ b/test/dates.t.cpp @@ -55,7 +55,7 @@ void testInit (UnitTest& t, const std::string& value, Variant& var) //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { - UnitTest t (106); + UnitTest t (105); Variant sunday; testInit (t, "sunday", sunday); Variant monday; testInit (t, "monday", monday); @@ -172,7 +172,6 @@ int main (int, char**) t.ok (now < someday, "now < someday"); t.ok (goodfriday < easter, "goodfriday < easter"); t.ok (easter < eastermonday, "easter < eastermonday"); - t.ok (easter < midsommarafton, "easter < midsommarafton"); t.ok (midsommarafton < midsommar, "midsommarafton < midsommar"); t.ok (juhannus == midsommarafton, "juhannus == midsommarafton"); From 70dc1cc9ae8a12731d6e2c82a206be5ca9ee6eea Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 28 Apr 2016 21:02:09 -0400 Subject: [PATCH 0049/1455] L10N: Fixed ambiguity in the esp-ESP localization - Thanks to Fidel Mato. --- ChangeLog | 2 ++ src/l10n/esp-ESP.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 51e851e1e..a07851ba8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,8 @@ - Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' virtual tag. - Removed deprecated 'alias._query' setting. +- Fixed ambiguity in the esp-ESP localization + (thanks to Fidel Mato). ------ current release --------------------------- diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index 4ca54b673..c46fd745e 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -1048,7 +1048,7 @@ #define STRING_UTIL_CONFIRM_NO "no" // |esp-ESP|==|eng-USA| #define STRING_UTIL_CONFIRM_ALL "todos" #define STRING_UTIL_CONFIRM_ALL_U "Todos" -#define STRING_UTIL_CONFIRM_QUIT "sal" +#define STRING_UTIL_CONFIRM_QUIT "canc" #define STRING_UTIL_GIBIBYTES "GiB" // |esp-ESP|==|eng-USA| #define STRING_UTIL_MEBIBYTES "MiB" // |esp-ESP|==|eng-USA| #define STRING_UTIL_KIBIBYTES "KiB" // |esp-ESP|==|eng-USA| From f79afb62698947866d4e483878cef0991a1e1b9c Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 1 May 2016 22:21:36 +0200 Subject: [PATCH 0050/1455] NEWS: Deprecate new-uuid verbosity option --- ChangeLog | 2 ++ NEWS | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index a07851ba8..41913b9e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,8 @@ - Removed deprecated 'alias._query' setting. - Fixed ambiguity in the esp-ESP localization (thanks to Fidel Mato). +- Deprecated the 'new-uuid' verbosity option, since its functionality can be + removed by merging with 'new-id'. ------ current release --------------------------- diff --git a/NEWS b/NEWS index 84f42d004..b97c47840 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ Newly Deprecated Features in Taskwarrior 2.6.0 - The 'DUETODAY' virtual tag is a synonym for the 'TODAY' virtual tag, and is not needed. + - The 'new-uuid' verbosity option is to be removed due to being redundant, its + functionality will be merged with 'new-id' option. Removed Features in 2.6.0 From d27cb75ec1701004d1687bf096f1d86ed7b056d3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 8 May 2016 16:36:25 -0400 Subject: [PATCH 0051/1455] util: Corrected comment --- src/util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 2db86148d..e36bc251d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -399,8 +399,8 @@ int execute ( #undef max //////////////////////////////////////////////////////////////////////////////// -// Accept a list of projects, and return an indented list -// that reflects the hierarchy. +// Accept a list of projects, and return an indented list that reflects the +// hierarchy. // // Input - "one" // "one.two" From 30c81c3046e795e6d493bfe35aca01948b6b5f06 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 8 May 2016 16:37:19 -0400 Subject: [PATCH 0052/1455] ColTypeDate: Fixed countdown format only showing values in the past --- src/columns/ColTypeDate.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/columns/ColTypeDate.cpp b/src/columns/ColTypeDate.cpp index c46f87eca..33cdc96b3 100644 --- a/src/columns/ColTypeDate.cpp +++ b/src/columns/ColTypeDate.cpp @@ -94,8 +94,7 @@ void ColumnTypeDate::measure (Task& task, unsigned int& minimum, unsigned int& m else if (_style == "countdown") { ISO8601d now; - if (now > date) - minimum = maximum = ISO8601p (now - date).formatVague ().length (); + minimum = maximum = ISO8601p (now - date).formatVague ().length (); } else if (_style == "julian") { @@ -167,8 +166,7 @@ void ColumnTypeDate::render ( else if (_style == "countdown") { ISO8601d now; - if (now > date) - renderStringRight (lines, width, color, ISO8601p (now - date).formatVague ()); + renderStringRight (lines, width, color, ISO8601p (now - date).formatVague ()); } else if (_style == "julian") renderStringRight (lines, width, color, format (date.toJulian (), 13, 12)); From b47fc523b90e58623d740e9b58af47c7e1bbc685 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 8 May 2016 16:41:24 -0400 Subject: [PATCH 0053/1455] Task: Corrected false-positive warning about relative dates --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 41913b9e4..e031b691b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,8 @@ (thanks to Fidel Mato). - Deprecated the 'new-uuid' verbosity option, since its functionality can be removed by merging with 'new-id'. +- Correct a false-positive warning when a due date is removed and a wait is + added. ------ current release --------------------------- From 53b526074f90ffdcda7431f8108c62153f2dfc03 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 20 May 2016 10:56:20 -0500 Subject: [PATCH 0054/1455] Cleanup: Removed debug output --- src/Task.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Task.cpp b/src/Task.cpp index d53f8a540..0e8cbf9bc 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -2008,7 +2008,6 @@ float Task::urgency_blocking () const // It came from the Command base object, but doesn't really belong there either. void Task::modify (modType type, bool text_required /* = false */) { - context.debug ("Task::modify"); std::string label = " MODIFICATION "; // Need this for later comparison. From 2720ea5a30b01b23556ea0cb978a5c54e0107215 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 20 May 2016 11:13:46 -0500 Subject: [PATCH 0055/1455] TW-1806: project:ide is not allowed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Thanks to Slaven ʙanovic. --- AUTHORS | 1 + ChangeLog | 2 ++ src/Eval.cpp | 2 +- src/columns/ColProject.cpp | 31 +++++++++++++++++++++++-------- src/l10n/deu-DEU.h | 1 + src/l10n/eng-USA.h | 1 + src/l10n/epo-RUS.h | 1 + src/l10n/esp-ESP.h | 1 + src/l10n/fra-FRA.h | 1 + src/l10n/ita-ITA.h | 1 + src/l10n/jpn-JPN.h | 1 + src/l10n/pol-POL.h | 1 + src/l10n/por-PRT.h | 1 + 13 files changed, 36 insertions(+), 9 deletions(-) diff --git a/AUTHORS b/AUTHORS index 24b3f475a..dec886fdb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -291,3 +291,4 @@ suggestions: Reg Yaroslav Molochko Michael Meier + Slaven ʙanovic diff --git a/ChangeLog b/ChangeLog index e031b691b..8145a2e5f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,8 @@ pending tasks. - TW-1795 Calendar underline on Day padding (thanks to Renato Alves). +- TW-1806 project:ide is not allowed + (thanks to Slaven ʙanovic). - Added 'juhannus' as a synonym for 'midsommarafton' (thanks to Lynoure Braakman). - Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' diff --git a/src/Eval.cpp b/src/Eval.cpp index 7a4d9fc61..9736d0981 100644 --- a/src/Eval.cpp +++ b/src/Eval.cpp @@ -387,7 +387,7 @@ void Eval::evaluatePostfixStack ( // If there is more than one variant left on the stack, then the original // expression was not valid. if (values.size () != 1) - throw std::string (STRING_EVAL_NO_EVAL); + throw std::string (STRING_EVAL_NOT_EXPRESSION); result = values[0]; } diff --git a/src/columns/ColProject.cpp b/src/columns/ColProject.cpp index 0e803aae9..f94a967f0 100644 --- a/src/columns/ColProject.cpp +++ b/src/columns/ColProject.cpp @@ -124,15 +124,30 @@ void ColumnProject::modify (Task& task, const std::string& value) if (lexer.token (domRef, type) && type == Lexer::Type::dom) { - Eval e; - e.addSource (domSource); - e.addSource (namedDates); - contextTask = task; + try + { + Eval e; + e.addSource (domSource); + e.addSource (namedDates); + contextTask = task; - Variant v; - e.evaluateInfixExpression (value, v); - task.set (_name, (std::string) v); - context.debug (label + _name + " <-- '" + (std::string) v + "' <-- '" + value + "'"); + Variant v; + e.evaluateInfixExpression (value, v); + task.set (_name, (std::string) v); + context.debug (label + _name + " <-- '" + (std::string) v + "' <-- '" + value + "'"); + } + catch (const std::string& e) + { + // If the expression failed because it didn't look like an expression, + // simply store it as-is. + if (e == STRING_EVAL_NOT_EXPRESSION) + { + task.set (_name, value); + context.debug (label + _name + " <-- '" + value + "'"); + } + else + throw; + } } else { diff --git a/src/l10n/deu-DEU.h b/src/l10n/deu-DEU.h index 3135d37ac..960195312 100644 --- a/src/l10n/deu-DEU.h +++ b/src/l10n/deu-DEU.h @@ -681,6 +681,7 @@ #define STRING_EVAL_UNSUPPORTED "Nicht unterstützter Operator: '{1}'." #define STRING_EVAL_OP_EXPECTED "Operator erwartet." #define STRING_EVAL_NO_EVAL "Der Ausdruck konnte nicht ausgewertet werden." +#define STRING_EVAL_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Ungültige Klammerung in Ausdruck." // edit diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 84de21d6b..0e58ee66a 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -679,6 +679,7 @@ #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_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Mismatched parentheses in expression" // edit diff --git a/src/l10n/epo-RUS.h b/src/l10n/epo-RUS.h index cb07b51e7..fa09d5ee6 100644 --- a/src/l10n/epo-RUS.h +++ b/src/l10n/epo-RUS.h @@ -681,6 +681,7 @@ #define STRING_EVAL_UNSUPPORTED "Ne subtenas infikson '{1}'." #define STRING_EVAL_OP_EXPECTED "Anticipis infikson." #define STRING_EVAL_NO_EVAL "Ne povis kalkuli la esprimon." +#define STRING_EVAL_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Malbalancataj parentezoj en esprimo" // edit diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index c46fd745e..303f2723d 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -690,6 +690,7 @@ #define STRING_EVAL_UNSUPPORTED "Operador no soportado '{1}'." #define STRING_EVAL_OP_EXPECTED "Se esperaba operador." #define STRING_EVAL_NO_EVAL "La expresión podría no ser evaluada." +#define STRING_EVAL_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Paréntesis desemparejados en expresión" // edit diff --git a/src/l10n/fra-FRA.h b/src/l10n/fra-FRA.h index 4046ed457..5bb47aef0 100644 --- a/src/l10n/fra-FRA.h +++ b/src/l10n/fra-FRA.h @@ -681,6 +681,7 @@ #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_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Mismatched parentheses in expression" // edit diff --git a/src/l10n/ita-ITA.h b/src/l10n/ita-ITA.h index 95e0da6b2..86d8969d5 100644 --- a/src/l10n/ita-ITA.h +++ b/src/l10n/ita-ITA.h @@ -680,6 +680,7 @@ #define STRING_EVAL_UNSUPPORTED "Operatore non supportato '{1}'." #define STRING_EVAL_OP_EXPECTED "Operator expected." #define STRING_EVAL_NO_EVAL "The expression could not be evaluated." +#define STRING_EVAL_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Mismatched parentheses in expression" // edit diff --git a/src/l10n/jpn-JPN.h b/src/l10n/jpn-JPN.h index e82ba9bc7..4ef19a050 100644 --- a/src/l10n/jpn-JPN.h +++ b/src/l10n/jpn-JPN.h @@ -681,6 +681,7 @@ #define STRING_EVAL_UNSUPPORTED "Unsupported operator '{1}'." #define STRING_EVAL_OP_EXPECTED "Operator expected." #define STRING_EVAL_NO_EVAL "式を評価出来ません。" +#define STRING_EVAL_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Mismatched parentheses in expression" // edit diff --git a/src/l10n/pol-POL.h b/src/l10n/pol-POL.h index 1264c3f6f..c6e1d7723 100644 --- a/src/l10n/pol-POL.h +++ b/src/l10n/pol-POL.h @@ -681,6 +681,7 @@ #define STRING_EVAL_UNSUPPORTED "Niewspierany operator '{1}'." #define STRING_EVAL_OP_EXPECTED "Oczekiwany operator." #define STRING_EVAL_NO_EVAL "Wyrażenie nie może być przetworzone." +#define STRING_EVAL_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Niedopasowane nawiasy w wyrażeniu" // edit diff --git a/src/l10n/por-PRT.h b/src/l10n/por-PRT.h index 0de68ed5c..0c73f794e 100644 --- a/src/l10n/por-PRT.h +++ b/src/l10n/por-PRT.h @@ -681,6 +681,7 @@ #define STRING_EVAL_UNSUPPORTED "Operador não suportado '{1}'." #define STRING_EVAL_OP_EXPECTED "Operador em falta." #define STRING_EVAL_NO_EVAL "Não foi possível calcular a expressão." +#define STRING_EVAL_NOT_EXPRESSION "The value is not an expression." #define STRING_PAREN_MISMATCH "Parentesis incompatíveis na expressão." // edit From af8434b84525b0eec1ab7f66cec60a42b931e9d8 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 20 May 2016 14:41:08 -0500 Subject: [PATCH 0056/1455] TW-1807: dateformat lacks a flag to display day of week - Thanks to Ellington Santos. --- AUTHORS | 1 + ChangeLog | 2 ++ doc/man/taskrc.5.in | 2 ++ src/ISO8601.cpp | 1 + 4 files changed, 6 insertions(+) diff --git a/AUTHORS b/AUTHORS index dec886fdb..d79ffd0af 100644 --- a/AUTHORS +++ b/AUTHORS @@ -292,3 +292,4 @@ suggestions: Yaroslav Molochko Michael Meier Slaven ʙanovic + Ellington Santos diff --git a/ChangeLog b/ChangeLog index 8145a2e5f..a9e82ea6e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,8 @@ (thanks to Renato Alves). - TW-1806 project:ide is not allowed (thanks to Slaven ʙanovic). +- TW-1807 dateformat lacks a flag to display day of week + (thanks to Ellington Santos). - Added 'juhannus' as a synonym for 'midsommarafton' (thanks to Lynoure Braakman). - Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' diff --git a/doc/man/taskrc.5.in b/doc/man/taskrc.5.in index 83294dd83..837e94858 100644 --- a/doc/man/taskrc.5.in +++ b/doc/man/taskrc.5.in @@ -583,6 +583,8 @@ S two-digit seconds, for example 07 or 47 J three-digit Julian day, for example 023 or 365 .br j Julian day, for example 23 or 365 +.br +w Week day, for example 0 for Monday, 5 for Friday .RE .RE diff --git a/src/ISO8601.cpp b/src/ISO8601.cpp index bf3282627..2edf511af 100644 --- a/src/ISO8601.cpp +++ b/src/ISO8601.cpp @@ -1122,6 +1122,7 @@ const std::string ISO8601d::toString ( case 'S': formatted << std::setw (2) << std::setfill ('0') << this->second (); break; case 'j': formatted << this->dayOfYear (); break; case 'J': formatted << std::setw (3) << std::setfill ('0') << this->dayOfYear (); break; + case 'w': formatted << this->dayOfWeek (); break; default: formatted << static_cast (c); break; } } From 091122350c5f7d6d8ab3e17f820c3006e849da12 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 20 May 2016 14:47:34 -0500 Subject: [PATCH 0057/1455] Tests: Added 'w' dateformat test --- test/iso8601d.t.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/iso8601d.t.cpp b/test/iso8601d.t.cpp index 938532335..431b570ca 100644 --- a/test/iso8601d.t.cpp +++ b/test/iso8601d.t.cpp @@ -72,9 +72,9 @@ void testParse ( int main (int, char**) { #ifdef PRODUCT_TASKWARRIOR - UnitTest t (1025); + UnitTest t (1026); #else - UnitTest t (996); + UnitTest t (997); #endif ISO8601d iso; @@ -657,6 +657,7 @@ int main (int, char**) t.is (r32.toString ("v"), "44", "2015-10-28T12:55:00 -> v -> 44"); t.is (r32.toString ("J"), "301", "2015-10-28T12:55:00 -> J -> 301"); t.is (r32.toString ("j"), "301", "2015-10-28T12:55:00 -> j -> 301"); + t.is (r32.toString ("w"), "3", "2015-10-28T12:55:00 -> w -> 3"); // Test all parse options. ISO8601d r33 ("2015 10 28 19 28 01", "Y M D H N S"); From dd72bed28a2373d1d40432d3c9417e9c71b4f463 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 30 May 2016 14:04:49 -0400 Subject: [PATCH 0058/1455] ISO8601: Added ::sameQuarter --- src/ISO8601.cpp | 7 +++++++ src/ISO8601.h | 31 ++++++++++++++++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/ISO8601.cpp b/src/ISO8601.cpp index 2edf511af..8a94621b5 100644 --- a/src/ISO8601.cpp +++ b/src/ISO8601.cpp @@ -1574,6 +1574,13 @@ bool ISO8601d::sameMonth (const ISO8601d& rhs) const this->month () == rhs.month (); } +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::sameQuarter (const ISO8601d& rhs) const +{ + return (this->year () == rhs.year ()) && + ((this->month () - 1) / 4) == ((rhs.month () - 1) / 4); +} + //////////////////////////////////////////////////////////////////////////////// bool ISO8601d::sameYear (const ISO8601d& rhs) const { diff --git a/src/ISO8601.h b/src/ISO8601.h index c7b7cd027..b3f82e5aa 100644 --- a/src/ISO8601.h +++ b/src/ISO8601.h @@ -86,26 +86,27 @@ public: 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; + 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 sameQuarter (const ISO8601d&) const; + bool sameYear (const ISO8601d&) const; 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 + void operator-- (); // Prefix + void operator-- (int); // Postfix + void operator++ (); // Prefix + void operator++ (int); // Postfix private: void clear (); From fd69305ad3c8935805678c2a58e66cf0af6e2e9f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 30 May 2016 14:09:49 -0400 Subject: [PATCH 0059/1455] Tests: Added ::sameQuarter tests --- test/iso8601d.t.cpp | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/test/iso8601d.t.cpp b/test/iso8601d.t.cpp index 431b570ca..e6d67c481 100644 --- a/test/iso8601d.t.cpp +++ b/test/iso8601d.t.cpp @@ -72,9 +72,9 @@ void testParse ( int main (int, char**) { #ifdef PRODUCT_TASKWARRIOR - UnitTest t (1026); + UnitTest t (1032); #else - UnitTest t (997); + UnitTest t (1003); #endif ISO8601d iso; @@ -256,27 +256,31 @@ int main (int, char**) // Loose comparisons. ISO8601d left ("7/4/2008", "m/d/Y"); ISO8601d comp1 ("7/4/2008", "m/d/Y"); - t.ok (left.sameDay (comp1), "7/4/2008 is on the same day as 7/4/2008"); - t.ok (left.sameWeek (comp1), "7/4/2008 is on the same week as 7/4/2008"); - t.ok (left.sameMonth (comp1), "7/4/2008 is in the same month as 7/4/2008"); - t.ok (left.sameYear (comp1), "7/4/2008 is in the same year as 7/4/2008"); + t.ok (left.sameDay (comp1), "7/4/2008 is on the same day as 7/4/2008"); + t.ok (left.sameWeek (comp1), "7/4/2008 is on the same week as 7/4/2008"); + t.ok (left.sameMonth (comp1), "7/4/2008 is in the same month as 7/4/2008"); + t.ok (left.sameQuarter (comp1), "7/4/2008 is in the same quarter as 7/4/2008"); + t.ok (left.sameYear (comp1), "7/4/2008 is in the same year as 7/4/2008"); ISO8601d comp2 ("7/5/2008", "m/d/Y"); - t.notok (left.sameDay (comp2), "7/4/2008 is not on the same day as 7/5/2008"); - t.ok (left.sameMonth (comp2), "7/4/2008 is in the same month as 7/5/2008"); - t.ok (left.sameYear (comp2), "7/4/2008 is in the same year as 7/5/2008"); + t.notok (left.sameDay (comp2), "7/4/2008 is not on the same day as 7/5/2008"); + t.ok (left.sameMonth (comp2), "7/4/2008 is in the same month as 7/5/2008"); + t.ok (left.sameQuarter (comp2), "7/4/2008 is in the same quarter as 7/5/2008"); + t.ok (left.sameYear (comp2), "7/4/2008 is in the same year as 7/5/2008"); ISO8601d comp3 ("8/4/2008", "m/d/Y"); - t.notok (left.sameDay (comp3), "7/4/2008 is not on the same day as 8/4/2008"); - t.notok (left.sameWeek (comp3), "7/4/2008 is not on the same week as 8/4/2008"); - t.notok (left.sameMonth (comp3), "7/4/2008 is not in the same month as 8/4/2008"); - t.ok (left.sameYear (comp3), "7/4/2008 is in the same year as 8/4/2008"); + t.notok (left.sameDay (comp3), "7/4/2008 is not on the same day as 8/4/2008"); + t.notok (left.sameWeek (comp3), "7/4/2008 is not on the same week as 8/4/2008"); + t.notok (left.sameMonth (comp3), "7/4/2008 is not in the same month as 8/4/2008"); + t.ok (left.sameQuarter (comp3), "7/4/2008 is in the same quarter as 8/4/2008"); + t.ok (left.sameYear (comp3), "7/4/2008 is in the same year as 8/4/2008"); ISO8601d comp4 ("7/4/2009", "m/d/Y"); - t.notok (left.sameDay (comp4), "7/4/2008 is not on the same day as 7/4/2009"); - t.notok (left.sameWeek (comp3), "7/4/2008 is not on the same week as 7/4/2009"); - t.notok (left.sameMonth (comp4), "7/4/2008 is not in the same month as 7/4/2009"); - t.notok (left.sameYear (comp4), "7/4/2008 is not in the same year as 7/4/2009"); + t.notok (left.sameDay (comp4), "7/4/2008 is not on the same day as 7/4/2009"); + t.notok (left.sameWeek (comp4), "7/4/2008 is not on the same week as 7/4/2009"); + t.notok (left.sameMonth (comp4), "7/4/2008 is not in the same month as 7/4/2009"); + t.notok (left.sameQuarter (comp4), "7/4/2008 is not in the same quarter as 7/4/2009"); + t.notok (left.sameYear (comp4), "7/4/2008 is not in the same year as 7/4/2009"); // Validity. t.ok (ISO8601d::valid (2, 29, 2008), "valid: 2/29/2008"); @@ -528,6 +532,7 @@ int main (int, char**) ISO8601d r13 ("eom"); t.ok (r13.sameMonth (now), "eom in same month as now"); + t.ok (r13.sameQuarter (now), "eom in same quarter as now"); ISO8601d r14 ("eocm"); t.ok (r14.sameMonth (now), "eocm in same month as now"); @@ -546,6 +551,7 @@ int main (int, char**) ISO8601d r18 ("socm"); t.ok (r18.sameMonth (now), "socm in same month as now"); + t.ok (r18.sameQuarter (now), "socm in same quarter as now"); ISO8601d r19 ("soy"); t.notok (r19.sameYear (now), "soy not in same year as now"); From 630a1530e0e0495f602ec5b687630b54945b2882 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 30 May 2016 14:11:07 -0400 Subject: [PATCH 0060/1455] Task: Added QUARTER virtual tag --- src/Task.cpp | 20 ++++++++++++++++++++ src/Task.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/Task.cpp b/src/Task.cpp index 0e8cbf9bc..bfa1f8214 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -474,6 +474,25 @@ bool Task::is_duemonth () const return false; } +//////////////////////////////////////////////////////////////////////////////// +bool Task::is_duequarter () const +{ + if (has ("due")) + { + Task::status status = getStatus (); + + if (status != Task::completed && + status != Task::deleted) + { + ISO8601d due (get_date ("due")); + if (due.sameQuarter (ISO8601d ())) + return true; + } + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////// bool Task::is_dueyear () const { @@ -1235,6 +1254,7 @@ bool Task::hasTag (const std::string& tag) const if (tag == "OVERDUE") return is_overdue (); if (tag == "WEEK") return is_dueweek (); if (tag == "MONTH") return is_duemonth (); + if (tag == "QUARTER") return is_duequarter (); if (tag == "YEAR") return is_dueyear (); #endif if (tag == "ACTIVE") return has ("start"); diff --git a/src/Task.h b/src/Task.h index 474049179..b4cf6d336 100644 --- a/src/Task.h +++ b/src/Task.h @@ -107,6 +107,7 @@ public: bool is_duetomorrow () const; bool is_dueweek () const; bool is_duemonth () const; + bool is_duequarter () const; bool is_dueyear () const; bool is_overdue () const; bool is_udaPresent () const; From ed7097d5dac0d44f43d31481685d6583d3bfac15 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 30 May 2016 14:11:29 -0400 Subject: [PATCH 0061/1455] Task: Made better use of ::sameN methods --- src/Task.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Task.cpp b/src/Task.cpp index bfa1f8214..6a9e10f13 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -445,8 +445,7 @@ bool Task::is_dueweek () const status != Task::deleted) { ISO8601d due (get_date ("due")); - if (due >= ISO8601d ("socw") && - due <= ISO8601d ("eocw")) + if (due.sameWeek (ISO8601d ())) return true; } } @@ -465,8 +464,7 @@ bool Task::is_duemonth () const status != Task::deleted) { ISO8601d due (get_date ("due")); - if (due >= ISO8601d ("socm") && - due <= ISO8601d ("eocm")) + if (due.sameMonth (ISO8601d ())) return true; } } @@ -503,9 +501,8 @@ bool Task::is_dueyear () const if (status != Task::completed && status != Task::deleted) { - ISO8601d now; ISO8601d due (get_date ("due")); - if (now.year () == due.year ()) + if (due.sameYear (ISO8601d ())) return true; } } From 4711dd9e138549cc33dfaf87ec0930c03f8f4825 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 30 May 2016 14:13:03 -0400 Subject: [PATCH 0062/1455] Docs: Added QUARTER virtual tag --- ChangeLog | 1 + NEWS | 2 +- doc/man/task.1.in | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a9e82ea6e..dc1528b73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,7 @@ removed by merging with 'new-id'. - Correct a false-positive warning when a due date is removed and a wait is added. +- Added 'QUARTER' virtual tag. ------ current release --------------------------- diff --git a/NEWS b/NEWS index b97c47840..5317b9700 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,7 @@ New Features in Taskwarrior 2.6.0 - - + - The 'QUARTER' virutal tag was added. New Commands in Taskwarrior 2.6.0 diff --git a/doc/man/task.1.in b/doc/man/task.1.in index ac6707c6e..c279e2230 100644 --- a/doc/man/task.1.in +++ b/doc/man/task.1.in @@ -690,6 +690,7 @@ are: PENDING Matches if the task has pending status PRIORITY Matches if the task has a priority PROJECT Matches if the task has a project + QUARTER Matches if the task is due this quarter READY Matches if the task is actionable SCHEDULED Matches if the task is scheduled TAGGED Matches if the task has tags From e52709133db353e76d1a52f8cbe0313251046fc2 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 12 Jun 2016 14:58:10 -0400 Subject: [PATCH 0063/1455] TW-1813: Range filter doesn't work - Thanks to george js. --- AUTHORS | 1 + ChangeLog | 2 ++ 2 files changed, 3 insertions(+) diff --git a/AUTHORS b/AUTHORS index d79ffd0af..e4eb5a1c2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -293,3 +293,4 @@ suggestions: Michael Meier Slaven ʙanovic Ellington Santos + george js diff --git a/ChangeLog b/ChangeLog index dc1528b73..1d764c343 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,8 @@ (thanks to Slaven ʙanovic). - TW-1807 dateformat lacks a flag to display day of week (thanks to Ellington Santos). +- TW-1813 Range filter doesn't work + (thanks to george js). - Added 'juhannus' as a synonym for 'midsommarafton' (thanks to Lynoure Braakman). - Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' From c79ae0848cb5d7b3bbbcea0616c6887e7184946d Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 12 Jun 2016 21:02:37 +0200 Subject: [PATCH 0064/1455] TW-61: Extract only tasks with annotations - Thanks to Aikido Guy. - Note: This is just bookkeeping commit, the solution (+ANNOTATED virtual tag) is present since 2.3.0. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 1d764c343..bd9bd7ed1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ - TD-64 sync conflict deleted all annotations of the task (thanks to Markus Beppler, Konstantin Vorobyev). +- TW-61 Extract only tasks with annotations + (thanks to Aikido Guy) - TW-1785 Purge command to remove deleted tasks (thanks to Paul Beckingham) - TW-1772 Implementation of circular dependency detection is From 504c49090b1b3ea3336b4b19981c32edd1f1672e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Jun 2016 19:36:52 -0400 Subject: [PATCH 0065/1455] L10N: Removed unused strings --- src/l10n/deu-DEU.h | 8 -------- src/l10n/eng-USA.h | 8 -------- src/l10n/epo-RUS.h | 8 -------- src/l10n/esp-ESP.h | 8 -------- src/l10n/fra-FRA.h | 8 -------- src/l10n/ita-ITA.h | 8 -------- src/l10n/jpn-JPN.h | 8 -------- src/l10n/pol-POL.h | 8 -------- src/l10n/por-PRT.h | 8 -------- 9 files changed, 72 deletions(-) diff --git a/src/l10n/deu-DEU.h b/src/l10n/deu-DEU.h index 960195312..4cb7e32b7 100644 --- a/src/l10n/deu-DEU.h +++ b/src/l10n/deu-DEU.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "Divisionsrest von null kann nicht berechnet werden" #define STRING_VARIANT_SQRT_NEG "Quadratwurzel einer negativen Zahl kann nicht berechnet werden." -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "Fehler: Kein Monat hat mehr als 31 Tage." -#define STRING_DATES_ORD_MISMATCH "Fehler: Zahl und Ordinalsuffix passen nicht (z.B., '1st', nicht '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "Farbe '{1}' nicht erkannt." @@ -501,7 +495,6 @@ // STRING_CMD_DIAG_* strings all appear on the 'diag' command output. #define STRING_CMD_DIAG_USAGE "Platform, build and environment details" #define STRING_CMD_DIAG_PLATFORM "Platform" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Compiler" #define STRING_CMD_DIAG_VERSION "Version" #define STRING_CMD_DIAG_CAPS "Caps" @@ -760,7 +753,6 @@ #define STRING_ASSUME_INFO "Kein Befehl angegeben - nehme 'information' an." #define STRING_INFINITE_LOOP "Beende Ersetzung, weil mehr als {1} Änderungen durchgeführt wurden - Schutz vor Endlosschleifen." #define STRING_UDA_TYPE "UDAs müssen vom Typ 'string', 'date', 'duration' oder 'numeric' sein." -#define STRING_UDA_TYPE_MISSING "uda.{1}.type nicht gefunden. Das UDA '{1}' muss einen festgelegten Typ haben." #define STRING_UDA_NUMERIC "Der Wert '{1}' ist kein zulässiger Zahlenwert." #define STRING_UDA_COLLISION "Das UDA '{1}' hat den selben Namen wie eine eingebaute Eigenschaft, und ist daher nicht erlaubt." #define STRING_INVALID_MOD "Die '{1}'-Eigenschaft erlaubt keinen Wert '{2}'." diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 0e58ee66a..29575dad4 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "Cannot modulo zero" #define STRING_VARIANT_SQRT_NEG "Cannot take the square root of a negative number." -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "Error: no month has more than 31 days." -#define STRING_DATES_ORD_MISMATCH "Error: number and ordinal don't match (e.g., '1st', not '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "The color '{1}' is not recognized." @@ -499,7 +493,6 @@ // STRING_CMD_DIAG_* strings all appear on the 'diag' command output. #define STRING_CMD_DIAG_USAGE "Platform, build and environment details" #define STRING_CMD_DIAG_PLATFORM "Platform" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Compiler" #define STRING_CMD_DIAG_VERSION "Version" #define STRING_CMD_DIAG_CAPS "Caps" @@ -758,7 +751,6 @@ #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." #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." #define STRING_UDA_NUMERIC "The value '{1}' is not a valid numeric value." #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}'." diff --git a/src/l10n/epo-RUS.h b/src/l10n/epo-RUS.h index fa09d5ee6..6594bf211 100644 --- a/src/l10n/epo-RUS.h +++ b/src/l10n/epo-RUS.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "Ne povas moduli nulon" #define STRING_VARIANT_SQRT_NEG "Ne povas kalkuli kvadratan radikon de negativa nombro." -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "Eraro: nenia monato havas pli de 31 tagojn." -#define STRING_DATES_ORD_MISMATCH "Eraro: la ordosufikso ne kongruas kun la nombro (ĝuste '1st', malĝuste '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "Koloro '{1}' ne rekonata." @@ -501,7 +495,6 @@ // STRING_CMD_DIAG_* strings all appear on the 'diag' command output. #define STRING_CMD_DIAG_USAGE "Platform, build and environment details" #define STRING_CMD_DIAG_PLATFORM "Platform" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Compiler" #define STRING_CMD_DIAG_VERSION "Version" #define STRING_CMD_DIAG_CAPS "Caps" @@ -760,7 +753,6 @@ #define STRING_ASSUME_INFO "Nenia komando specifita. Supozanta 'information'." #define STRING_INFINITE_LOOP "Finis anstataŭon ĉar ekzistas pli de {1} ŝanĝoj - protekto kontraŭ senfina ripeton." #define STRING_UDA_TYPE "La tipo de uzanto-definitaj atributoj devas esti 'string', 'date', 'duration', aŭ 'numeric'." -#define STRING_UDA_TYPE_MISSING "Ne trovis uda.{1}.type. Oni devas specifid la tipo de UDA '{1}'." #define STRING_UDA_NUMERIC "Valoro '{1}' ne estas valida nombra valoro." #define STRING_UDA_COLLISION "UDA '{1}' kaj enkonstruita atributo havas la saman nomon. Tio estas malpermesita." #define STRING_INVALID_MOD "Atributo '{1}' ne permesas valoron '{2}'." diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index 303f2723d..e42d0b90f 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "No se puede modular cero" #define STRING_VARIANT_SQRT_NEG "No se puede calcular la raíz cuadrada de un tipo desconocido" -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "Error: no hay ningún mes que tenga más de 31 días." -#define STRING_DATES_ORD_MISMATCH "Error: el sufijo ordinal no corresponde al número (i.e. '1st', no '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "El color '{1}' no se reconoce." @@ -507,7 +501,6 @@ #define STRING_CMD_SYNC_TRUST_OBS "Los ajustes de 'taskd.trust' ahora solo pueden contener uno de los valores 'strict', 'ignore hostname' o 'allow all'." #define STRING_CMD_DIAG_USAGE "Detalles de plataforma, construcción y entorno" #define STRING_CMD_DIAG_PLATFORM "Plataforma" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Compilador" #define STRING_CMD_DIAG_VERSION "Versión" #define STRING_CMD_DIAG_CAPS "Capacidades" @@ -769,7 +762,6 @@ #define STRING_ASSUME_INFO "No especificó un comando - asumido 'information'." #define STRING_INFINITE_LOOP "Sustitución terminada debido a que se hicieron más de {1} cambios - protección contra ciclo eterno." #define STRING_UDA_TYPE "Los atributos definidos por el usuario solamente pueden ser de los tipos 'string', 'date', 'duration' o 'numeric'." -#define STRING_UDA_TYPE_MISSING "No se encontró uda.{1}.type . El UDA '{1}' debe tener algún tipo especificado." #define STRING_UDA_NUMERIC "El valor '{1}' no es un valor numérico válido." #define STRING_UDA_COLLISION "El UDA denominado '{1}' es el mismo que un atributo del núcleo, y no está permitido." #define STRING_INVALID_MOD "El atributo '{1}' no admite un valor '{2}'." diff --git a/src/l10n/fra-FRA.h b/src/l10n/fra-FRA.h index 5bb47aef0..46847ffa1 100644 --- a/src/l10n/fra-FRA.h +++ b/src/l10n/fra-FRA.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "Ne peut pas moduler zéro" #define STRING_VARIANT_SQRT_NEG "Ne peut pas calculer la racine carrée d'un nombre négatif." -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "Erreur : aucun mois n'a plus de 31 jours." -#define STRING_DATES_ORD_MISMATCH "Erreur : le nombre ne correspond pas à l'ordinal (ie '1st', pas '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "La couleur '{1}' n'est pas reconnue." @@ -501,7 +495,6 @@ // STRING_CMD_DIAG_* strings all appear on the 'diag' command output. #define STRING_CMD_DIAG_USAGE "Platform, build and environment details" #define STRING_CMD_DIAG_PLATFORM "Platform" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Compiler" #define STRING_CMD_DIAG_VERSION "Version" #define STRING_CMD_DIAG_CAPS "Caps" @@ -760,7 +753,6 @@ #define STRING_ASSUME_INFO "No command specified - assuming 'information'." #define STRING_INFINITE_LOOP "Substitution arrêté parce que plus de {1} changements ont été faits - protection contre les boucles infinies." #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 introuvable. L'ADU '{1}' doit avoir un type déclaré." #define STRING_UDA_NUMERIC "The value '{1}' is not a valid numeric value." #define STRING_UDA_COLLISION "L'ADU nommé '{1}' est le même qu'un attribut du noyau, et ce n'est pas autorisé." #define STRING_INVALID_MOD "The '{1}' attribute does not allow a value of '{2}'." diff --git a/src/l10n/ita-ITA.h b/src/l10n/ita-ITA.h index 86d8969d5..858b257da 100644 --- a/src/l10n/ita-ITA.h +++ b/src/l10n/ita-ITA.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "Cannot modulo zero" #define STRING_VARIANT_SQRT_NEG "Cannot take the square root of a negative number." -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "Error: no month has more than 31 days." -#define STRING_DATES_ORD_MISMATCH "Error: number and ordinal don't match (e.g., '1st', not '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "Il colore '{1}' non è riconosciuto." @@ -500,7 +494,6 @@ // STRING_CMD_DIAG_* strings all appear on the 'diag' command output. #define STRING_CMD_DIAG_USAGE "Dettagli su piattaforma, build e ambiente" #define STRING_CMD_DIAG_PLATFORM "Piattaforma" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Compilatore" #define STRING_CMD_DIAG_VERSION "Versione" #define STRING_CMD_DIAG_CAPS "Caps" @@ -759,7 +752,6 @@ #define STRING_ASSUME_INFO "Nessun comando specificato - si assume 'information'." #define STRING_INFINITE_LOOP "Sostituzione terminata poiché più di {1} modifiche sono state fatte - protezione da ciclo infinito" #define STRING_UDA_TYPE "Gli User defined attribute possono solo essere di tipo 'string', 'date', 'duration' o 'numeric'." -#define STRING_UDA_TYPE_MISSING "uda.{1}.type non trovato. L'UDA '{1}' deve avere un tipo specificato." #define STRING_UDA_NUMERIC "Il valore '{1}' non è un valore numerico valido." #define STRING_UDA_COLLISION "L'UDA '{1}' ha lo stesso nome di un attributo di sistema, e ciò non è permesso." #define STRING_INVALID_MOD "L'attributo '{1}' non ammette un valore pari a '{2}'." diff --git a/src/l10n/jpn-JPN.h b/src/l10n/jpn-JPN.h index 4ef19a050..4f53cba27 100644 --- a/src/l10n/jpn-JPN.h +++ b/src/l10n/jpn-JPN.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "零で剰余を取ることは出来ません。" #define STRING_VARIANT_SQRT_NEG "負の数は平方根を計算できません。" -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "エラー: 月の日付は31日まで。" -#define STRING_DATES_ORD_MISMATCH "Error: number and ordinal don't match (e.g., '1st', not '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "The color '{1}' is not recognized." @@ -501,7 +495,6 @@ // STRING_CMD_DIAG_* strings all appear on the 'diag' command output. #define STRING_CMD_DIAG_USAGE "Platform, build and environment details" #define STRING_CMD_DIAG_PLATFORM "Platform" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Compiler" #define STRING_CMD_DIAG_VERSION "Version" #define STRING_CMD_DIAG_CAPS "Caps" @@ -760,7 +753,6 @@ #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." #define STRING_UDA_NUMERIC "The value '{1}' is not a valid numeric value." #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}'." diff --git a/src/l10n/pol-POL.h b/src/l10n/pol-POL.h index c6e1d7723..8e5d82760 100644 --- a/src/l10n/pol-POL.h +++ b/src/l10n/pol-POL.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "Nie można uzyskać modulo z zera" #define STRING_VARIANT_SQRT_NEG "Nie można wyciągnąć pierwiastka kwadratowego z wartości ujemnej." -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "Błąd: żaden miesiąc nie ma więcej niż 31 dni." -#define STRING_DATES_ORD_MISMATCH "Błąd: niepoprawny sufix (np., '1st', nie '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "Kolor '{1}' nie został rozpoznany." @@ -501,7 +495,6 @@ // STRING_CMD_DIAG_* strings all appear on the 'diag' command output. #define STRING_CMD_DIAG_USAGE "Szczegóły platformy i środowiska budowania" #define STRING_CMD_DIAG_PLATFORM "Platforma" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Kompilator" #define STRING_CMD_DIAG_VERSION "Wersja" #define STRING_CMD_DIAG_CAPS "Flagi" @@ -760,7 +753,6 @@ #define STRING_ASSUME_INFO "Nie podano polecenia - zakładam 'information'." #define STRING_INFINITE_LOOP "Podstawienie anulowane ponieważ wykonano więcej niż {1} zmian - zabezpieczenie przed zapętleniem." #define STRING_UDA_TYPE "Atrybuty definiowane przez użytkownika mogą być typu 'string', 'date', 'duration' lub 'numeric'." -#define STRING_UDA_TYPE_MISSING "uda.{1}.type nie znaleziony. UDA '{1}' musi posiadać typ." #define STRING_UDA_NUMERIC "Wartość '{1}' nie jest poprawną wartością numeryczną." #define STRING_UDA_COLLISION "Nazwa UDA '{1}' jest jedną z nazw atrybutów podstawowych i dlatego jest niedozwolona." #define STRING_INVALID_MOD "Atrybut '{1}' nie zezwala na wartość '{2}'." diff --git a/src/l10n/por-PRT.h b/src/l10n/por-PRT.h index 0c73f794e..c8859b024 100644 --- a/src/l10n/por-PRT.h +++ b/src/l10n/por-PRT.h @@ -162,12 +162,6 @@ #define STRING_VARIANT_MOD_ZERO "Impossível calcular módulo de zero" #define STRING_VARIANT_SQRT_NEG "Impossível calcular a raiz quadrada de um número negativo." -// Dates -// -// These are errors generated when parsing date values. -#define STRING_DATES_MONTH_31 "Erro: nenhum mês tem mais de 31 dias." -#define STRING_DATES_ORD_MISMATCH "Erro: correspondencia inválida entre número e ordinal (usar '1st', e não '1nd')." - // Color #define STRING_COLOR_UNRECOGNIZED "A cor '{1}' não é reconhecida." @@ -501,7 +495,6 @@ // STRING_CMD_DIAG_* strings all appear on the 'diag' command output. #define STRING_CMD_DIAG_USAGE "Plataforma, versão e detalhes de ambiente" #define STRING_CMD_DIAG_PLATFORM "Plataforma" -#define STRING_CMD_DIAG_UNKNOWN "" #define STRING_CMD_DIAG_COMPILER "Compilador" #define STRING_CMD_DIAG_VERSION "Versão" #define STRING_CMD_DIAG_CAPS "Capacidades" @@ -760,7 +753,6 @@ #define STRING_ASSUME_INFO "Nenhum comando especificado - assumindo 'information'." #define STRING_INFINITE_LOOP "Substituição terminada. Efectuadas mais de {1} alterações - protecção de ciclos infinitos." #define STRING_UDA_TYPE "Atributos definidos pelo utilizador (UDAs) apenas podem ser do tipo 'texto', 'data', 'duração' ou 'numérico'." -#define STRING_UDA_TYPE_MISSING "uda.{1}.type não encontrado. É necessário especificar um tipo no 'UDA' '{1}'." #define STRING_UDA_NUMERIC "O valor '{1}' não é um valor numérico válido." #define STRING_UDA_COLLISION "O UDA '{1}' tem o mesmo nome que um atributo interno, tal não é permitido." #define STRING_INVALID_MOD "O atributo '{1}' não permite o valor '{2}'." From d031d4282ff1fc12d2930d7f37e3a82be52a6f69 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Jun 2016 19:38:36 -0400 Subject: [PATCH 0066/1455] TW-1820: Install with -DLANGUAGE=2 flag not work. - Thanks to E. Manuel Cerr'on Angeles --- AUTHORS | 1 + ChangeLog | 2 ++ src/l10n/esp-ESP.h | 1 + 3 files changed, 4 insertions(+) diff --git a/AUTHORS b/AUTHORS index e4eb5a1c2..93f150806 100644 --- a/AUTHORS +++ b/AUTHORS @@ -294,3 +294,4 @@ suggestions: Slaven ʙanovic Ellington Santos george js + E. Manuel Cerr'on Angeles diff --git a/ChangeLog b/ChangeLog index bd9bd7ed1..b22ccf462 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,8 @@ (thanks to Ellington Santos). - TW-1813 Range filter doesn't work (thanks to george js). +- TW-1820 Install with -DLANGUAGE=2 flag not work. + (thanks to E. Manuel Cerr'on Angeles) - Added 'juhannus' as a synonym for 'midsommarafton' (thanks to Lynoure Braakman). - Deprecated the 'DUETODAY' virtual tag, which is a synonym for the 'TODAY' diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index e42d0b90f..1a512c4d7 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -769,6 +769,7 @@ #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 "Los filtros de línea de comando no están soportados por este comando." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." #define STRING_ERROR_BAD_STATUS "El estatus '{1}' no es válido." // Feedback From 4de7617c1b50187f7ab2ae6caf0972f490c5b62e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 24 Jun 2016 22:23:49 -0400 Subject: [PATCH 0067/1455] Docs: Removed one suggestion for reporting bugs --- NEWS | 4 ---- 1 file changed, 4 deletions(-) diff --git a/NEWS b/NEWS index 5317b9700..b54713bc4 100644 --- a/NEWS +++ b/NEWS @@ -43,10 +43,6 @@ encounter a bug, please enter a new issue at: https://bug.tasktools.org -Or you can also report the issue in the forums at: - - https://answers.tasktools.org - Or just send a message to: support@taskwarrior.org From 77b443ce8b68d0e226ed0333ee878741e4131163 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:12:00 -0400 Subject: [PATCH 0068/1455] libshared: Added libshared --- .gitmodules | 3 +++ src/libshared | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 src/libshared diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..919cbabcb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/libshared"] + path = src/libshared + url = https://git.tasktools.org/scm/tm/libshared.git diff --git a/src/libshared b/src/libshared new file mode 160000 index 000000000..144d37263 --- /dev/null +++ b/src/libshared @@ -0,0 +1 @@ +Subproject commit 144d37263c52aef3e0959e1b891785da3911ece5 From 2e8763364b61fccf51848c4ab5a7fa6135972732 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:22:27 -0400 Subject: [PATCH 0069/1455] libshared: Integrated the submodule - Integrated RX. --- src/CMakeLists.txt | 77 ++++++++--------- src/RX.cpp | 159 ------------------------------------ src/RX.h | 58 ------------- src/columns/CMakeLists.txt | 1 + src/commands/CMakeLists.txt | 1 + test/rx.t.cpp | 142 -------------------------------- 6 files changed, 41 insertions(+), 397 deletions(-) delete mode 100644 src/RX.cpp delete mode 100644 src/RX.h delete mode 100644 test/rx.t.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fde10cd3c..d3d7880c5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,52 +3,53 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/commands ${CMAKE_SOURCE_DIR}/src/columns + ${CMAKE_SOURCE_DIR}/src/libshared/src ${TASK_INCLUDE_DIRS}) -set (task_SRCS CLI2.cpp CLI2.h - Color.cpp Color.h - Config.cpp Config.h - Context.cpp Context.h - DOM.cpp DOM.h - Dates.cpp Dates.h - Eval.cpp Eval.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 - RX.cpp RX.h - TDB2.cpp TDB2.h - Task.cpp Task.h - Timer.cpp Timer.h - TLSClient.cpp TLSClient.h - Variant.cpp Variant.h - ViewTask.cpp ViewTask.h - ViewText.cpp ViewText.h - dependency.cpp - feedback.cpp - i18n.h - legacy.cpp - recur.cpp - rules.cpp - sort.cpp - text.cpp text.h - utf8.cpp utf8.h - util.cpp util.h - wcwidth6.cpp) +add_library (task CLI2.cpp CLI2.h + Color.cpp Color.h + Config.cpp Config.h + Context.cpp Context.h + DOM.cpp DOM.h + Dates.cpp Dates.h + Eval.cpp Eval.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 + TDB2.cpp TDB2.h + Task.cpp Task.h + Timer.cpp Timer.h + TLSClient.cpp TLSClient.h + Variant.cpp Variant.h + ViewTask.cpp ViewTask.h + ViewText.cpp ViewText.h + dependency.cpp + feedback.cpp + i18n.h + legacy.cpp + recur.cpp + rules.cpp + sort.cpp + text.cpp text.h + utf8.cpp utf8.h + util.cpp util.h + wcwidth6.cpp) + +add_library (libshared libshared/src/RX.cpp libshared/src/RX.h) -add_library (task STATIC ${task_SRCS}) add_executable (task_executable main.cpp) add_executable (calc_executable calc.cpp) add_executable (lex_executable lex.cpp) # Yes, 'task' is included twice, otherwise linking fails on assorted OSes. -target_link_libraries (task_executable task commands columns task ${TASK_LIBRARIES}) -target_link_libraries (calc_executable task commands columns task ${TASK_LIBRARIES}) -target_link_libraries (lex_executable task commands columns task ${TASK_LIBRARIES}) +target_link_libraries (task_executable task commands columns libshared task ${TASK_LIBRARIES}) +target_link_libraries (calc_executable task commands columns libshared task ${TASK_LIBRARIES}) +target_link_libraries (lex_executable task commands columns libshared task ${TASK_LIBRARIES}) set_property (TARGET task_executable PROPERTY OUTPUT_NAME "task") diff --git a/src/RX.cpp b/src/RX.cpp deleted file mode 100644 index b68a063b7..000000000 --- a/src/RX.cpp +++ /dev/null @@ -1,159 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -//////////////////////////////////////////////////////////////////////////////// -RX::RX () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -RX::RX ( - const std::string& pattern, - bool case_sensitive /* = true */) -: _compiled (false) -, _pattern (pattern) -, _case_sensitive (case_sensitive) -{ - compile (); -} - -//////////////////////////////////////////////////////////////////////////////// -RX::RX (const RX& other) -{ - _compiled = false; - _pattern = other._pattern; - _case_sensitive = other._case_sensitive; -} - -//////////////////////////////////////////////////////////////////////////////// -RX::~RX () -{ - if (_compiled) - regfree (&_regex); -} - -//////////////////////////////////////////////////////////////////////////////// -RX& RX::operator= (const RX& other) -{ - _compiled = false; - _pattern = other._pattern; - _case_sensitive = other._case_sensitive; - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -void RX::compile () -{ - if (! _compiled) - { - memset (&_regex, 0, sizeof (regex_t)); - - int result; - if ((result = regcomp (&_regex, _pattern.c_str (), -#if defined REG_ENHANCED - REG_ENHANCED | REG_EXTENDED | REG_NEWLINE | -#else - REG_EXTENDED | REG_NEWLINE | -#endif - (_case_sensitive ? 0 : REG_ICASE))) != 0) - { - char message[256]; - regerror (result, &_regex, message, 256); - throw std::string (message); - } - - _compiled = true; - } -} - -//////////////////////////////////////////////////////////////////////////////// -bool RX::match (const std::string& in) -{ - if (! _compiled) - compile (); - - return regexec (&_regex, in.c_str (), 0, nullptr, 0) == 0 ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool RX::match ( - std::vector& matches, - const std::string& in) -{ - if (! _compiled) - compile (); - - regmatch_t rm[2]; - int offset = 0; - int length = in.length (); - while (regexec (&_regex, in.c_str () + offset, 2, &rm[0], 0) == 0 && - offset < length) - { - matches.push_back (in.substr (rm[0].rm_so + offset, rm[0].rm_eo - rm[0].rm_so)); - offset += rm[0].rm_eo; - - // Protection against zero-width patterns causing infinite loops. - if (rm[0].rm_so == rm[0].rm_eo) - ++offset; - } - - return matches.size () ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool RX::match ( - std::vector & start, - std::vector & end, - const std::string& in) -{ - if (! _compiled) - compile (); - - regmatch_t rm[2]; - int offset = 0; - int length = in.length (); - while (regexec (&_regex, in.c_str () + offset, 2, &rm[0], 0) == 0 && - offset < length) - { - start.push_back (rm[0].rm_so + offset); - end.push_back (rm[0].rm_eo + offset); - offset += rm[0].rm_eo; - - // Protection against zero-width patterns causing infinite loops. - if (rm[0].rm_so == rm[0].rm_eo) - ++offset; - } - - return start.size () ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/RX.h b/src/RX.h deleted file mode 100644 index b98371113..000000000 --- a/src/RX.h +++ /dev/null @@ -1,58 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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_RX -#define INCLUDED_RX - -#include -#include -#include - -class RX -{ -public: - RX (); - RX (const std::string&, bool caseSensitive = true); - RX (const RX&); - ~RX (); - RX& operator= (const RX&); - - bool match (const std::string&); - bool match (std::vector&, const std::string&); - bool match (std::vector &, std::vector &, const std::string&); - -private: - void compile (); - -private: - bool _compiled {false}; - std::string _pattern {}; - bool _case_sensitive {false}; - regex_t _regex; -}; - -#endif - diff --git a/src/columns/CMakeLists.txt b/src/columns/CMakeLists.txt index 76ccdc0fc..0bfffc941 100644 --- a/src/columns/CMakeLists.txt +++ b/src/columns/CMakeLists.txt @@ -3,6 +3,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/commands ${CMAKE_SOURCE_DIR}/src/columns + ${CMAKE_SOURCE_DIR}/src/libshared/src ${TASK_INCLUDE_DIRS}) set (columns_SRCS Column.cpp Column.h diff --git a/src/commands/CMakeLists.txt b/src/commands/CMakeLists.txt index 575e351e7..188a8ef81 100644 --- a/src/commands/CMakeLists.txt +++ b/src/commands/CMakeLists.txt @@ -3,6 +3,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/commands ${CMAKE_SOURCE_DIR}/src/columns + ${CMAKE_SOURCE_DIR}/src/libshared/src ${TASK_INCLUDE_DIRS}) set (commands_SRCS Command.cpp Command.h diff --git a/test/rx.t.cpp b/test/rx.t.cpp deleted file mode 100644 index 134bacf97..000000000 --- a/test/rx.t.cpp +++ /dev/null @@ -1,142 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -Context context; - -int main (int, char**) -{ - UnitTest ut (26); - - // Ensure environment has no influence. - unsetenv ("TASKDATA"); - unsetenv ("TASKRC"); - - std::string text = "This is a test."; - - RX r1 ("i. ", true); - ut.ok (r1.match (text), text + " =~ /i. /"); - - std::vector matches; - ut.ok (r1.match (matches, text), text + " =~ /i. /"); - ut.ok (matches.size () == 2, "2 match"); - ut.is (matches[0], "is ", "$1 == is\\s"); - ut.is (matches[1], "is ", "$1 == is\\s"); - - text = "abcdefghijklmnopqrstuvwxyz"; - - RX r3 ("t..", true); - ut.ok (r3.match (text), "t.."); - - RX r4 ("T..", false); - ut.ok (r4.match (text), "T.."); - - RX r5 ("T..", true); - ut.ok (!r5.match (text), "! T.."); - - text = "this is a test of the regex engine."; - // |...:....|....:....|....:....|....: - - RX r6 ("^this"); - ut.ok (r6.match (text), "^this matches"); - - RX r7 ("engine\\.$"); - ut.ok (r7.match (text), "engine\\.$ matches"); - - std::vector results; - std::vector start; - std::vector end; - RX r8 ("e..", true); - ut.ok (r8.match (results, text), "e.. there are matches"); - ut.ok (r8.match (start, end, text), "e.. there are matches"); - ut.is (results.size (), (size_t) 4, "e.. == 4 matches"); - ut.is (results[0], "est", "e..[0] == 'est'"); - ut.is (start[0], 11, "e..[0] == 11->"); - ut.is (end[0], 14, "e..[0] == ->14"); - - results.clear (); - RX r9 ("e", true); - ut.ok (r9.match (results, text), "e there are matches"); - ut.is (results.size (), (size_t) 6, "e == 6 matches"); - - start.clear (); - end.clear (); - ut.ok (r9.match (start, end, text), "e there are matches"); - ut.is (start.size (), (size_t) 6, "e == 6 matches"); - -#if defined(DARWIN) || defined(CYGWIN) || defined(FREEBSD) || defined(OPENBSD) - text = "this is the end."; - ut.pass (text + " =~ /\\bthe/"); - ut.pass (text + " =~ /the\\b/"); - ut.pass (text + " =~ /\\bthe\\b/"); -#elif defined(SOLARIS) - RX r10 ("\\"); - ut.ok (r11.match (text), text + " =~ /the\\>/"); - - RX r12 ("\\"); - ut.ok (r12.match (text), text + " =~ /\\/"); -#else - RX r10 ("\\bthe"); - text = "this is the end."; - ut.ok (r10.match (text), text + " =~ /\\bthe/"); - - RX r11 ("the\\b"); - ut.ok (r11.match (text), text + " =~ /the\\b/"); - - RX r12 ("\\bthe\\b"); - ut.ok (r12.match (text), text + " =~ /\\bthe\\b/"); -#endif - -#if defined(DARWIN) - text = "D0"; - RX r13 ("D\\d"); - ut.ok (r13.match (text), text + " =~ /D\\d/"); -#else - ut.skip (" =~ /D\\d/"); -#endif - - text = "D0"; - RX r14 ("D[[:digit:]]"); - ut.ok (r14.match (text), text + " =~ /D[[:digit:]]/"); - - text = "D0"; - RX r15 ("D[0-9]"); - ut.ok (r15.match (text), text + " =~ /D[0-9]/"); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// - From 806043f0ad0e824b248d384415dbaf20b2ce8d24 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:23:15 -0400 Subject: [PATCH 0070/1455] Tests: Removed RX tests --- test/.gitignore | 1 - test/CMakeLists.txt | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/.gitignore b/test/.gitignore index 368a48a6e..aae3c5865 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -18,7 +18,6 @@ lexer.t list.t msg.t nibbler.t -rx.t t.t taskmod.t tdb2.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 411b61571..4bb26533e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,11 +10,12 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/commands ${CMAKE_SOURCE_DIR}/src/columns + ${CMAKE_SOURCE_DIR}/src/libshared/src ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) set (test_SRCS autocomplete.t col.t color.t config.t fs.t i18n.t json.t list.t - msg.t nibbler.t rx.t t.t tdb2.t text.t utf8.t util.t view.t + msg.t nibbler.t t.t tdb2.t text.t utf8.t util.t view.t json_test lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t @@ -32,7 +33,7 @@ add_custom_target (build_tests DEPENDS ${test_SRCS} foreach (src_FILE ${test_SRCS}) add_executable (${src_FILE} "${src_FILE}.cpp" test.cpp) - target_link_libraries (${src_FILE} task commands task columns ${TASK_LIBRARIES}) + target_link_libraries (${src_FILE} task commands task columns libshared ${TASK_LIBRARIES}) endforeach (src_FILE) configure_file(run_all run_all COPYONLY) From 8291e97e870e1a9fffe470302bb23f00d0c8af8a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:27:57 -0400 Subject: [PATCH 0071/1455] libshared: Integrated JSON --- src/CMakeLists.txt | 6 +- src/JSON.cpp | 494 --------------------------------------------- src/JSON.h | 135 ------------- 3 files changed, 4 insertions(+), 631 deletions(-) delete mode 100644 src/JSON.cpp delete mode 100644 src/JSON.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d3d7880c5..231508ba1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,7 +17,6 @@ add_library (task CLI2.cpp CLI2.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 @@ -40,7 +39,10 @@ add_library (task CLI2.cpp CLI2.h util.cpp util.h wcwidth6.cpp) -add_library (libshared libshared/src/RX.cpp libshared/src/RX.h) +add_library (libshared libshared/src/JSON.cpp libshared/src/JSON.h + libshared/src/Pig.cpp libshared/src/Pig.h + libshared/src/RX.cpp libshared/src/RX.h + libshared/src/unicode.cpp libshared/src/unicode.h) add_executable (task_executable main.cpp) add_executable (calc_executable calc.cpp) diff --git a/src/JSON.cpp b/src/JSON.cpp deleted file mode 100644 index a18256362..000000000 --- a/src/JSON.cpp +++ /dev/null @@ -1,494 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -const char *json_encode[] = { - "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", - "\\b", "\\t", "\\n", "\x0b", "\\f", "\\r", "\x0e", "\x0f", - "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", - "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", - "\x20", "\x21", "\\\"", "\x23", "\x24", "\x25", "\x26", "\x27", - "\x28", "\x29", "\x2a", "\x2b", "\x2c", "\x2d", "\x2e", "\\/", - "\x30", "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", - "\x38", "\x39", "\x3a", "\x3b", "\x3c", "\x3d", "\x3e", "\x3f", - "\x40", "\x41", "\x42", "\x43", "\x44", "\x45", "\x46", "\x47", - "\x48", "\x49", "\x4a", "\x4b", "\x4c", "\x4d", "\x4e", "\x4f", - "\x50", "\x51", "\x52", "\x53", "\x54", "\x55", "\x56", "\x57", - "\x58", "\x59", "\x5a", "\x5b", "\\\\", "\x5d", "\x5e", "\x5f", - "\x60", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", - "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", - "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", - "\x78", "\x79", "\x7a", "\x7b", "\x7c", "\x7d", "\x7e", "\x7f", - "\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87", - "\x88", "\x89", "\x8a", "\x8b", "\x8c", "\x8d", "\x8e", "\x8f", - "\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97", - "\x98", "\x99", "\x9a", "\x9b", "\x9c", "\x9d", "\x9e", "\x9f", - "\xa0", "\xa1", "\xa2", "\xa3", "\xa4", "\xa5", "\xa6", "\xa7", - "\xa8", "\xa9", "\xaa", "\xab", "\xac", "\xad", "\xae", "\xaf", - "\xb0", "\xb1", "\xb2", "\xb3", "\xb4", "\xb5", "\xb6", "\xb7", - "\xb8", "\xb9", "\xba", "\xbb", "\xbc", "\xbd", "\xbe", "\xbf", - "\xc0", "\xc1", "\xc2", "\xc3", "\xc4", "\xc5", "\xc6", "\xc7", - "\xc8", "\xc9", "\xca", "\xcb", "\xcc", "\xcd", "\xce", "\xcf", - "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7", - "\xd8", "\xd9", "\xda", "\xdb", "\xdc", "\xdd", "\xde", "\xdf", - "\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7", - "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef", - "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7", - "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff" -}; - -//////////////////////////////////////////////////////////////////////////////// -json::value* json::value::parse (Nibbler& nibbler) -{ - json::value* v; - if ((v = json::object::parse (nibbler)) || - (v = json::array::parse (nibbler)) || - (v = json::string::parse (nibbler)) || - (v = json::number::parse (nibbler)) || - (v = json::literal::parse (nibbler))) - return v; - - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -json::jtype json::value::type () -{ - return json::j_value; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string json::value::dump () const -{ - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -json::string::string (const std::string& other) -{ - _data = other; -} - -//////////////////////////////////////////////////////////////////////////////// -json::string* json::string::parse (Nibbler& nibbler) -{ - std::string value; - if (nibbler.getQuoted ('"', value)) - { - json::string* s = new json::string (); - s->_data = value; - return s; - } - - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -json::jtype json::string::type () -{ - return json::j_string; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string json::string::dump () const -{ - return std::string ("\"") + _data + "\""; -} - -//////////////////////////////////////////////////////////////////////////////// -json::number* json::number::parse (Nibbler& nibbler) -{ - double d; - if (nibbler.getNumber (d)) - { - json::number* s = new json::number (); - s->_dvalue = d; - return s; - } - - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -json::jtype json::number::type () -{ - return json::j_number; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string json::number::dump () const -{ - return format (_dvalue); -} - -//////////////////////////////////////////////////////////////////////////////// -json::number::operator double () const -{ - return _dvalue; -} - -//////////////////////////////////////////////////////////////////////////////// -json::literal* json::literal::parse (Nibbler& nibbler) -{ - if (nibbler.getLiteral ("null")) - { - json::literal* s = new json::literal (); - s->_lvalue = nullvalue; - return s; - } - else if (nibbler.getLiteral ("false")) - { - json::literal* s = new json::literal (); - s->_lvalue = falsevalue; - return s; - } - else if (nibbler.getLiteral ("true")) - { - json::literal* s = new json::literal (); - s->_lvalue = truevalue; - return s; - } - - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -json::jtype json::literal::type () -{ - return json::j_literal; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string json::literal::dump () const -{ - if (_lvalue == nullvalue) return "null"; - else if (_lvalue == falsevalue) return "false"; - else return "true"; -} - -//////////////////////////////////////////////////////////////////////////////// -json::array::~array () -{ - for (auto& i : _data) - delete i; -} - -//////////////////////////////////////////////////////////////////////////////// -json::array* json::array::parse (Nibbler& nibbler) -{ - Nibbler n (nibbler); - n.skipWS (); - if (n.skip ('[')) - { - n.skipWS (); - - json::array* arr = new json::array (); - - json::value* value; - if ((value = json::value::parse (n))) - { - arr->_data.push_back (value); - value = NULL; // Not a leak. Looks like a leak. - n.skipWS (); - while (n.skip (',')) - { - n.skipWS (); - - if ((value = json::value::parse (n))) - { - arr->_data.push_back (value); - n.skipWS (); - } - else - { - delete arr; - throw format (STRING_JSON_MISSING_VALUE, (int) n.cursor ()); - } - } - } - - if (n.skip (']')) - { - nibbler = n; - return arr; - } - else - throw format (STRING_JSON_MISSING_BRACKET, (int) n.cursor ()); - - delete arr; - } - - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -json::jtype json::array::type () -{ - return json::j_array; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string json::array::dump () const -{ - std::string output; - output += "["; - - for (auto i = _data.begin (); i != _data.end (); ++i) - { - if (i != _data.begin ()) - output += ","; - - output += (*i)->dump (); - } - - output += "]"; - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -json::object::~object () -{ - for (auto& i : _data) - delete i.second; -} - -//////////////////////////////////////////////////////////////////////////////// -json::object* json::object::parse (Nibbler& nibbler) -{ - Nibbler n (nibbler); - n.skipWS (); - if (n.skip ('{')) - { - n.skipWS (); - - json::object* obj = new json::object (); - - std::string name; - json::value* value; - if (json::object::parse_pair (n, name, value)) - { - obj->_data.insert (std::pair (name, value)); - value = NULL; // Not a leak. Looks like a leak. - - n.skipWS (); - while (n.skip (',')) - { - n.skipWS (); - - if (json::object::parse_pair (n, name, value)) - { - obj->_data.insert (std::pair (name, value)); - n.skipWS (); - } - else - { - delete obj; - throw format (STRING_JSON_MISSING_VALUE, (int) n.cursor ()); - } - } - } - - if (n.skip ('}')) - { - nibbler = n; - return obj; - } - else - throw format (STRING_JSON_MISSING_BRACE, (int) n.cursor ()); - - delete obj; - } - - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -bool json::object::parse_pair ( - Nibbler& nibbler, - std::string& name, - json::value*& val) -{ - Nibbler n (nibbler); - - if (n.getQuoted ('"', name)) - { - n.skipWS (); - if (n.skip (':')) - { - n.skipWS (); - if ((val = json::value::parse (n))) - { - nibbler = n; - return true; - } - else - throw format (STRING_JSON_MISSING_VALUE2, (int) n.cursor ()); - } - else - throw format (STRING_JSON_MISSING_COLON, (int) n.cursor ()); - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -json::jtype json::object::type () -{ - return json::j_object; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string json::object::dump () const -{ - std::string output; - output += "{"; - - for (auto i = _data.begin (); i != _data.end (); ++i) - { - if (i != _data.begin ()) - output += ","; - - output += "\"" + i->first + "\":"; - output += i->second->dump (); - } - - output += "}"; - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -json::value* json::parse (const std::string& input) -{ - json::value* root = NULL; - - Nibbler n (input); - n.skipWS (); - - if (n.next () == '{') root = json::object::parse (n); - else if (n.next () == '[') root = json::array::parse (n); - else - throw format (STRING_JSON_MISSING_OPEN, (int) n.cursor ()); - - // Check for end condition. - n.skipWS (); - if (!n.depleted ()) - { - delete root; - throw format (STRING_JSON_EXTRA_CHARACTERS, (int) n.cursor ()); - } - - return root; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string json::encode (const std::string& input) -{ - std::string output; - output.reserve ((input.size () * 6) / 5); // 20% increase. - - auto last = input.begin (); - for (auto i = input.begin (); i != input.end (); ++i) - { - switch (*i) - { - // Simple translations. - case '"': - case '\\': - case '/': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - output.append (last, i); - output += json_encode[(unsigned char)(*i)]; - last = i + 1; - - // Default NOP. - } - } - - output.append (last, input.end ()); - - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string json::decode (const std::string& input) -{ - std::string output; - output.reserve (input.size ()); // Same size. - - size_t pos = 0; - - while (pos < input.length ()) - { - if (input[pos] == '\\') - { - ++pos; - switch (input[pos]) - { - // Simple translations. - case '"': output += '"'; break; - case '\\': output += '\\'; break; - case '/': output += '/'; break; - case 'b': output += '\b'; break; - case 'f': output += '\f'; break; - case 'n': output += '\n'; break; - case 'r': output += '\r'; break; - case 't': output += '\t'; break; - - // Compose a UTF8 unicode character. - case 'u': - output += utf8_character (utf8_codepoint (input.substr (++pos))); - pos += 3; - break; - - // If it is an unrecognized sequence, do nothing. - default: - output += '\\'; - output += input[pos]; - break; - } - ++pos; - } - else - { - size_t next_backslash = input.find ('\\', pos); - output.append (input, pos, next_backslash - pos); - pos = next_backslash; - } - } - - return output; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/JSON.h b/src/JSON.h deleted file mode 100644 index 3408b3a37..000000000 --- a/src/JSON.h +++ /dev/null @@ -1,135 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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_JSON -#define INCLUDED_JSON - -#include -#include -#include -#include - -namespace json -{ - enum jtype - { - j_value, // 0 - j_object, // 1 - j_array, // 2 - j_string, // 3 - j_number, // 4 - j_literal // 5 - }; - - class value - { - public: - value () {} - virtual ~value () {} - static value* parse (Nibbler&); - virtual jtype type (); - virtual std::string dump () const; - }; - - class string : public value - { - public: - string () {} - string (const std::string&); - ~string () {} - static string* parse (Nibbler&); - jtype type (); - std::string dump () const; - - public: - std::string _data; - }; - - class number : public value - { - public: - number () : _dvalue (0.0) {} - ~number () {} - static number* parse (Nibbler&); - jtype type (); - std::string dump () const; - operator double () const; - - public: - double _dvalue; - }; - - class literal : public value - { - public: - literal () : _lvalue (none) {} - ~literal () {} - static literal* parse (Nibbler&); - jtype type (); - std::string dump () const; - - public: - enum literal_value {none, nullvalue, falsevalue, truevalue}; - literal_value _lvalue; - }; - - class array : public value - { - public: - array () {} - ~array (); - static array* parse (Nibbler&); - jtype type (); - std::string dump () const; - - public: - std::vector _data; - }; - - class object : public value - { - public: - object () {} - ~object (); - static object* parse (Nibbler&); - static bool parse_pair (Nibbler&, std::string&, value*&); - jtype type (); - std::string dump () const; - - public: - std::map _data; - }; - - // Parser entry point. - value* parse (const std::string&); - - // Encode/decode for JSON entities. - std::string encode (const std::string&); - std::string decode (const std::string&); -} - -#endif -//////////////////////////////////////////////////////////////////////////////// From 802020a7bb0828baae65aea3d534756a1b6e9577 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:28:15 -0400 Subject: [PATCH 0072/1455] Git: Now ignores liblibshared.a --- src/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/.gitignore b/src/.gitignore index 6b6ab2aee..99a78c14e 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -3,3 +3,4 @@ Makefile.in debug calc lex +liblibshared.a From 59f4475466ce86a003fc7cb7a224c9cb828fbbad Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Jun 2016 17:42:59 -0400 Subject: [PATCH 0073/1455] Tests: Removed JSON tests --- test/.gitignore | 1 - test/CMakeLists.txt | 4 +- test/json.t.cpp | 189 ---------------------------------------- test/json/1.json | 23 ----- test/json/2.json | 11 --- test/json/3.json | 26 ------ test/json/4.json | 88 ------------------- test/json/5.json | 27 ------ test/json/6.json | 2 - test/json/e1.json | 1 - test/json/e2.json | 30 ------- test/json/e3.json | 4 - test/json/e4.json | 26 ------ test/json/e5.json | 70 --------------- test/json/e6.json | 17 ---- test/json/e7.json | 34 -------- test/json/e8.json | 36 -------- test/json/facebook.json | 44 ---------- test/json/flikr.json | 21 ----- test/json/interop.json | 41 --------- test/json/iphone.json | 77 ---------------- test/json/twitter.json | 50 ----------- test/json/youtube.json | 53 ----------- test/json_test.cpp | 87 ------------------ test/json_test.t | 83 ------------------ 25 files changed, 2 insertions(+), 1043 deletions(-) delete mode 100644 test/json.t.cpp delete mode 100644 test/json/1.json delete mode 100644 test/json/2.json delete mode 100644 test/json/3.json delete mode 100644 test/json/4.json delete mode 100644 test/json/5.json delete mode 100644 test/json/6.json delete mode 100644 test/json/e1.json delete mode 100644 test/json/e2.json delete mode 100644 test/json/e3.json delete mode 100644 test/json/e4.json delete mode 100644 test/json/e5.json delete mode 100644 test/json/e6.json delete mode 100644 test/json/e7.json delete mode 100644 test/json/e8.json delete mode 100644 test/json/facebook.json delete mode 100644 test/json/flikr.json delete mode 100644 test/json/interop.json delete mode 100644 test/json/iphone.json delete mode 100644 test/json/twitter.json delete mode 100644 test/json/youtube.json delete mode 100644 test/json_test.cpp delete mode 100755 test/json_test.t diff --git a/test/.gitignore b/test/.gitignore index aae3c5865..dd2709758 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -13,7 +13,6 @@ fs.t i18n.t iso8601d.t iso8601p.t -json.t lexer.t list.t msg.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4bb26533e..6a4d15834 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,9 +14,9 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) -set (test_SRCS autocomplete.t col.t color.t config.t fs.t i18n.t json.t list.t +set (test_SRCS autocomplete.t col.t color.t config.t fs.t i18n.t list.t msg.t nibbler.t t.t tdb2.t text.t utf8.t util.t view.t - json_test lexer.t iso8601d.t iso8601p.t eval.t dates.t + lexer.t iso8601d.t iso8601p.t eval.t dates.t variant_add.t variant_and.t variant_cast.t variant_divide.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t variant_inequal.t variant_lt.t variant_lte.t variant_match.t diff --git a/test/json.t.cpp b/test/json.t.cpp deleted file mode 100644 index 9c3a948ad..000000000 --- a/test/json.t.cpp +++ /dev/null @@ -1,189 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright 2006 - 2016, 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 - -Context context; - -const char *positive_tests[] = -{ - "{}", - - " { } ", - - "[]", - - "{\"one\":1}", - - "{\n\"one\"\n:\n1\n}\n", - - " { \"one\" : 1 } ", - - "{\"name\":123, \"array\":[1,2,3.4], \"object\":{\"m1\":\"v1\", \"m2\":\"v2\"}}", - - "{\"name\":\"value\",\"array\":[\"one\",\"two\"],\"object\":{\"name2\":123,\"literal\":false}}", - - "{\n" - "\"ticket\": { \"type\":\"add\", \"client\":\"taskwarrior 2.x\"},\n" - "\"auth\": { \"user\":\"paul\", \"org\":\"gbf\", \"key\":\".........\",\n" - " \"locale\":\"en-US\" },\n" - "\n" - "\"add\": { \"description\":\"Wash the dog\",\n" - " \"project\":\"home\",\n" - " \"due\":\"20101101T000000Z\" }\n" - "}", - - "{" - "\"ticket\":{" - "\"type\":\"synch\"," - "\"client\":\"taskd-test-suite 1.0\"" - "}," - "\"synch\":{" - "\"user\":{" - "\"data\":[" - "{" - "\"uuid\":\"11111111-1111-1111-1111-111111111111\"," - "\"status\":\"pending\"," - "\"description\":\"This is a test\"," - "\"entry\":\"20110111T124000Z\"" - "}" - "]," - "\"synch\":\"key\"" - "}" - "}," - "\"auth\":{" - "\"org\":\"gbf\"," - "\"user\":\"Paul Beckingham\"," - "\"key\":\"K\"," - "\"locale\":\"en-US\"" - "}" - "}" -}; - -#define NUM_POSITIVE_TESTS (sizeof (positive_tests) / sizeof (positive_tests[0])) - -const char *negative_tests[] = -{ - "", - "{", - "}", - "[", - "]", - "foo", - "[?]" -}; - -#define NUM_NEGATIVE_TESTS (sizeof (negative_tests) / sizeof (negative_tests[0])) - -//////////////////////////////////////////////////////////////////////////////// -int main (int, char**) -{ - UnitTest t (NUM_POSITIVE_TESTS + NUM_NEGATIVE_TESTS + 22); - - // Ensure environment has no influence. - unsetenv ("TASKDATA"); - unsetenv ("TASKRC"); - - // Positive tests. - for (unsigned int i = 0; i < NUM_POSITIVE_TESTS; ++i) - { - try - { - json::value* root = json::parse (positive_tests[i]); - t.ok (root, std::string ("positive: ") + positive_tests[i]); - if (root) - { - t.diag (root->dump ()); - delete root; - } - } - - catch (const std::string& e) { t.diag (e); } - catch (...) { t.diag ("Unknown error"); } - } - - // Negative tests. - for (unsigned int i = 0; i < NUM_NEGATIVE_TESTS; ++i) - { - try - { - json::value* root = json::parse (negative_tests[i]); - t.is ((const char*) root, (const char*) NULL, - std::string ("negative: ") + negative_tests[i]); - } - - catch (const std::string& e) { t.pass (e); } - catch (...) { t.fail ("Unknown error"); } - } - - // Other tests. - try - { - // Regular unit tests. - t.is (json::encode ("1\b2"), "1\\b2", "json::encode slashslashb -> slashslashslashslashb"); - t.is (json::decode ("1\\b2"), "1\b2", "json::decode slashslashslashslashb -> slashslashb"); - - t.is (json::encode ("1\n2"), "1\\n2", "json::encode slashslashn -> slashslashslashslashn"); - t.is (json::decode ("1\\n2"), "1\n2", "json::decode slashslashslashslashn -> slashslashn"); - - t.is (json::encode ("1\r2"), "1\\r2", "json::encode slashslashr -> slashslashslashslashr"); - t.is (json::decode ("1\\r2"), "1\r2", "json::decode slashslashslashslashr -> slashslashr"); - - t.is (json::encode ("1\t2"), "1\\t2", "json::encode slashslasht -> slashslashslashslasht"); - t.is (json::decode ("1\\t2"), "1\t2", "json::decode slashslashslashslasht -> slashslasht"); - - t.is (json::encode ("1\\2"), "1\\\\2", "json::encode slashslash -> slashslashslashslash"); - t.is (json::decode ("1\\\\2"), "1\\2", "json::decode slashslashslashslash -> slashslash"); - - t.is (json::encode ("1\x2"), "1\x2", "json::encode slashslashx -> slashslashx(NOP)"); - t.is (json::decode ("1\x2"), "1\x2", "json::decode slashslashx -> slashslashx(NOP)"); - - t.is (json::encode ("1€2"), "1€2", "json::encode € -> €"); - t.is (json::decode ("1\\u20ac2"), "1€2", "json::decode slashslashu20ac -> €"); - - std::string encoded = json::encode ("one\\"); - t.is (encoded, "one\\\\", "json::encode oneslashslashslashslash -> oneslashslashslashslashslashslashslashslash"); - t.is ((int)encoded.length (), 5, "json::encode oneslashslashslashslash -> length 5"); - t.is (encoded[0], 'o', "json::encode oneslashslashslashslash[0] -> o"); - t.is (encoded[1], 'n', "json::encode oneslashslashslashslash[1] -> n"); - t.is (encoded[2], 'e', "json::encode oneslashslashslashslash[2] -> e"); - t.is (encoded[3], '\\', "json::encode oneslashslashslashslash[3] -> slashslash"); - t.is (encoded[4], '\\', "json::encode oneslashslashslashslash[4] -> slashslash"); - - t.is (json::decode (encoded), "one\\", "json::decode oneslashslashslashslashslashslashslashslash -> oneslashslashslashslash"); - } - - catch (const std::string& e) {t.diag (e);} - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/test/json/1.json b/test/json/1.json deleted file mode 100644 index 81d48c0d1..000000000 --- a/test/json/1.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "glossary": { - "title": "example glossary", - "GlossDiv": { - "title": "S", - "GlossList": { - "GlossEntry": { - "ID": "SGML", - "SortAs": "SGML", - "GlossTerm": "Standard Generalized Markup Language", - "Acronym": "SGML", - "Abbrev": "ISO 8879:1986", - "GlossDef": { - "para": "A meta-markup language, used to create markup languages such as DocBook.", - "GlossSeeAlso": ["GML", "XML"] - }, - "GlossSee": "markup" - } - } - } - } -} - diff --git a/test/json/2.json b/test/json/2.json deleted file mode 100644 index 5600991a4..000000000 --- a/test/json/2.json +++ /dev/null @@ -1,11 +0,0 @@ -{"menu": { - "id": "file", - "value": "File", - "popup": { - "menuitem": [ - {"value": "New", "onclick": "CreateNewDoc()"}, - {"value": "Open", "onclick": "OpenDoc()"}, - {"value": "Close", "onclick": "CloseDoc()"} - ] - } -}} diff --git a/test/json/3.json b/test/json/3.json deleted file mode 100644 index 9b820d853..000000000 --- a/test/json/3.json +++ /dev/null @@ -1,26 +0,0 @@ -{"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } -}} diff --git a/test/json/4.json b/test/json/4.json deleted file mode 100644 index 9eea6ad6e..000000000 --- a/test/json/4.json +++ /dev/null @@ -1,88 +0,0 @@ -{"web-app": { - "servlet": [ - { - "servlet-name": "cofaxCDS", - "servlet-class": "org.cofax.cds.CDSServlet", - "init-param": { - "configGlossary:installationAt": "Philadelphia, PA", - "configGlossary:adminEmail": "ksm@pobox.com", - "configGlossary:poweredBy": "Cofax", - "configGlossary:poweredByIcon": "/images/cofax.gif", - "configGlossary:staticPath": "/content/static", - "templateProcessorClass": "org.cofax.WysiwygTemplate", - "templateLoaderClass": "org.cofax.FilesTemplateLoader", - "templatePath": "templates", - "templateOverridePath": "", - "defaultListTemplate": "listTemplate.htm", - "defaultFileTemplate": "articleTemplate.htm", - "useJSP": false, - "jspListTemplate": "listTemplate.jsp", - "jspFileTemplate": "articleTemplate.jsp", - "cachePackageTagsTrack": 200, - "cachePackageTagsStore": 200, - "cachePackageTagsRefresh": 60, - "cacheTemplatesTrack": 100, - "cacheTemplatesStore": 50, - "cacheTemplatesRefresh": 15, - "cachePagesTrack": 200, - "cachePagesStore": 100, - "cachePagesRefresh": 10, - "cachePagesDirtyRead": 10, - "searchEngineListTemplate": "forSearchEnginesList.htm", - "searchEngineFileTemplate": "forSearchEngines.htm", - "searchEngineRobotsDb": "WEB-INF/robots.db", - "useDataStore": true, - "dataStoreClass": "org.cofax.SqlDataStore", - "redirectionClass": "org.cofax.SqlRedirection", - "dataStoreName": "cofax", - "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", - "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", - "dataStoreUser": "sa", - "dataStorePassword": "dataStoreTestQuery", - "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", - "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", - "dataStoreInitConns": 10, - "dataStoreMaxConns": 100, - "dataStoreConnUsageLimit": 100, - "dataStoreLogLevel": "debug", - "maxUrlLength": 500}}, - { - "servlet-name": "cofaxEmail", - "servlet-class": "org.cofax.cds.EmailServlet", - "init-param": { - "mailHost": "mail1", - "mailHostOverride": "mail2"}}, - { - "servlet-name": "cofaxAdmin", - "servlet-class": "org.cofax.cds.AdminServlet"}, - - { - "servlet-name": "fileServlet", - "servlet-class": "org.cofax.cds.FileServlet"}, - { - "servlet-name": "cofaxTools", - "servlet-class": "org.cofax.cms.CofaxToolsServlet", - "init-param": { - "templatePath": "toolstemplates/", - "log": 1, - "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", - "logMaxSize": "", - "dataLog": 1, - "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", - "dataLogMaxSize": "", - "removePageCache": "/content/admin/remove?cache=pages&id=", - "removeTemplateCache": "/content/admin/remove?cache=templates&id=", - "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", - "lookInContext": 1, - "adminGroupID": 4, - "betaServer": true}}], - "servlet-mapping": { - "cofaxCDS": "/", - "cofaxEmail": "/cofaxutil/aemail/*", - "cofaxAdmin": "/admin/*", - "fileServlet": "/static/*", - "cofaxTools": "/tools/*"}, - - "taglib": { - "taglib-uri": "cofax.tld", - "taglib-location": "/WEB-INF/tlds/cofax.tld"}}} diff --git a/test/json/5.json b/test/json/5.json deleted file mode 100644 index 49980ca25..000000000 --- a/test/json/5.json +++ /dev/null @@ -1,27 +0,0 @@ -{"menu": { - "header": "SVG Viewer", - "items": [ - {"id": "Open"}, - {"id": "OpenNew", "label": "Open New"}, - null, - {"id": "ZoomIn", "label": "Zoom In"}, - {"id": "ZoomOut", "label": "Zoom Out"}, - {"id": "OriginalView", "label": "Original View"}, - null, - {"id": "Quality"}, - {"id": "Pause"}, - {"id": "Mute"}, - null, - {"id": "Find", "label": "Find..."}, - {"id": "FindAgain", "label": "Find Again"}, - {"id": "Copy"}, - {"id": "CopyAgain", "label": "Copy Again"}, - {"id": "CopySVG", "label": "Copy SVG"}, - {"id": "ViewSVG", "label": "View SVG"}, - {"id": "ViewSource", "label": "View Source"}, - {"id": "SaveAs", "label": "Save As"}, - null, - {"id": "Help"}, - {"id": "About", "label": "About Adobe CVG Viewer..."} - ] -}} diff --git a/test/json/6.json b/test/json/6.json deleted file mode 100644 index 8711288cb..000000000 --- a/test/json/6.json +++ /dev/null @@ -1,2 +0,0 @@ -[{"styleFocus":"GROWTH","creationTime":"2008-01-21","preferences":{"kfe.elite-rankings":"hide","guitarPromoClosed":"1","kfe.last_viewed_feature":"1"},"nickName":"Pascal-Louis Perez","showFlag":true,"firstName":"Pascal-Louis","points":0,"id":8,"industryFocus":"TECHNOLOGY","externalIds":[{"platform":"FACEBOOK","id":219948}],"useRealName":true,"shard":8,"concentrationFocus":"LESS_THAN_10","passwordSalt":3567830610840546163,"validatedEmails":["pascal.louis.perez@gmail.com","pascal@kaching.com","pascal@cs.stanford.edu"],"city":"Geneve","rankLevel":"BASIC","experiences":["KACHING","DEVELOPMENT","LOGIN_SYSTEM","ADMIN","RESEARCH","RANKINGS"],"marketCapFocus":"LARGE","picture":"sqr8.jpg","interests":{"MY_WALL":["EMAIL"]},"nonValidatedEmails":["pascal.loui-s.perez@gmail.com"],"showPicture":true,"lastName":"Perez","tradingFrequencyFocus":"BUY_AND_HOLD","validatedPrimaryEmail":"pascal.louis.perez@gmail.com","country":"CH","sessions":[{"d":"p","parameters":{"facebookSessionKey":"a9f133eed207196a563b0ca7-219948","facebookUserId":"219948"},"k":"qOtXSepsfrc=","platform":"FACEBOOK"},{"d":"s","k":"O7p3i91IXa8="},{"d":"s","k":"fexhG/MSXr0="},{"d":"s","k":"YUkWZMK4ors="},{"d":"s","k":"ETfFsm0svdg="}],"primaryEmail":"pascal.louis.perez@gmail.com","investmentStrategy":"Hire people who can manage my assets for me. I'm lousy.","lastLogin":"2008-12-17 12:45:25.000","portfolioId":219948}] - diff --git a/test/json/e1.json b/test/json/e1.json deleted file mode 100644 index 0dd16dd01..000000000 --- a/test/json/e1.json +++ /dev/null @@ -1 +0,0 @@ -[ 100, 500, 300, 200, 400 ] diff --git a/test/json/e2.json b/test/json/e2.json deleted file mode 100644 index c3e38240b..000000000 --- a/test/json/e2.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "color": "red", - "value": "#f00" - }, - { - "color": "green", - "value": "#0f0" - }, - { - "color": "blue", - "value": "#00f" - }, - { - "color": "cyan", - "value": "#0ff" - }, - { - "color": "magenta", - "value": "#f0f" - }, - { - "color": "yellow", - "value": "#ff0" - }, - { - "color": "black", - "value": "#000" - } -] diff --git a/test/json/e3.json b/test/json/e3.json deleted file mode 100644 index 93fd18825..000000000 --- a/test/json/e3.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "color": "red", - "value": "#f00" -} diff --git a/test/json/e4.json b/test/json/e4.json deleted file mode 100644 index ef2b65474..000000000 --- a/test/json/e4.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "0001", - "type": "donut", - "name": "Cake", - "ppu": 0.55, - "batters": - { - "batter": - [ - { "id": "1001", "type": "Regular" }, - { "id": "1002", "type": "Chocolate" }, - { "id": "1003", "type": "Blueberry" }, - { "id": "1004", "type": "Devil's Food" } - ] - }, - "topping": - [ - { "id": "5001", "type": "None" }, - { "id": "5002", "type": "Glazed" }, - { "id": "5005", "type": "Sugar" }, - { "id": "5007", "type": "Powdered Sugar" }, - { "id": "5006", "type": "Chocolate with Sprinkles" }, - { "id": "5003", "type": "Chocolate" }, - { "id": "5004", "type": "Maple" } - ] -} diff --git a/test/json/e5.json b/test/json/e5.json deleted file mode 100644 index 70ddac09a..000000000 --- a/test/json/e5.json +++ /dev/null @@ -1,70 +0,0 @@ -[ - { - "id": "0001", - "type": "donut", - "name": "Cake", - "ppu": 0.55, - "batters": - { - "batter": - [ - { "id": "1001", "type": "Regular" }, - { "id": "1002", "type": "Chocolate" }, - { "id": "1003", "type": "Blueberry" }, - { "id": "1004", "type": "Devil's Food" } - ] - }, - "topping": - [ - { "id": "5001", "type": "None" }, - { "id": "5002", "type": "Glazed" }, - { "id": "5005", "type": "Sugar" }, - { "id": "5007", "type": "Powdered Sugar" }, - { "id": "5006", "type": "Chocolate with Sprinkles" }, - { "id": "5003", "type": "Chocolate" }, - { "id": "5004", "type": "Maple" } - ] - }, - { - "id": "0002", - "type": "donut", - "name": "Raised", - "ppu": 0.55, - "batters": - { - "batter": - [ - { "id": "1001", "type": "Regular" } - ] - }, - "topping": - [ - { "id": "5001", "type": "None" }, - { "id": "5002", "type": "Glazed" }, - { "id": "5005", "type": "Sugar" }, - { "id": "5003", "type": "Chocolate" }, - { "id": "5004", "type": "Maple" } - ] - }, - { - "id": "0003", - "type": "donut", - "name": "Old Fashioned", - "ppu": 0.55, - "batters": - { - "batter": - [ - { "id": "1001", "type": "Regular" }, - { "id": "1002", "type": "Chocolate" } - ] - }, - "topping": - [ - { "id": "5001", "type": "None" }, - { "id": "5002", "type": "Glazed" }, - { "id": "5003", "type": "Chocolate" }, - { "id": "5004", "type": "Maple" } - ] - } -] diff --git a/test/json/e6.json b/test/json/e6.json deleted file mode 100644 index e55e960fa..000000000 --- a/test/json/e6.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "id": "0001", - "type": "donut", - "name": "Cake", - "image": - { - "url": "images/0001.jpg", - "width": 200, - "height": 200 - }, - "thumbnail": - { - "url": "images/thumbnails/0001.jpg", - "width": 32, - "height": 32 - } -} diff --git a/test/json/e7.json b/test/json/e7.json deleted file mode 100644 index adbd088e7..000000000 --- a/test/json/e7.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "items": - { - "item": - [ - { - "id": "0001", - "type": "donut", - "name": "Cake", - "ppu": 0.55, - "batters": - { - "batter": - [ - { "id": "1001", "type": "Regular" }, - { "id": "1002", "type": "Chocolate" }, - { "id": "1003", "type": "Blueberry" }, - { "id": "1004", "type": "Devil's Food" } - ] - }, - "topping": - [ - { "id": "5001", "type": "None" }, - { "id": "5002", "type": "Glazed" }, - { "id": "5005", "type": "Sugar" }, - { "id": "5007", "type": "Powdered Sugar" }, - { "id": "5006", "type": "Chocolate with Sprinkles" }, - { "id": "5003", "type": "Chocolate" }, - { "id": "5004", "type": "Maple" } - ] - } - ] - } -} diff --git a/test/json/e8.json b/test/json/e8.json deleted file mode 100644 index 468c919b4..000000000 --- a/test/json/e8.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "items": - { - "item": - [ - { - "id": "0001", - "type": "donut", - "name": "Cake", - "ppu": 0.55, - "batters": - { - "batter": - [ - { "id": "1001", "type": "Regular" }, - { "id": "1002", "type": "Chocolate" }, - { "id": "1003", "type": "Blueberry" }, - { "id": "1004", "type": "Devil's Food" } - ] - }, - "topping": - [ - { "id": "5001", "type": "None" }, - { "id": "5002", "type": "Glazed" }, - { "id": "5005", "type": "Sugar" }, - { "id": "5007", "type": "Powdered Sugar" }, - { "id": "5006", "type": "Chocolate with Sprinkles" }, - { "id": "5003", "type": "Chocolate" }, - { "id": "5004", "type": "Maple" } - ] - } - - - ] - } -} diff --git a/test/json/facebook.json b/test/json/facebook.json deleted file mode 100644 index 6627bf8df..000000000 --- a/test/json/facebook.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "data": [ - { - "id": "X999_Y999", - "from": { - "name": "Tom Brady", "id": "X12" - }, - "message": "Looking forward to 2010!", - "actions": [ - { - "name": "Comment", - "link": "http://www.facebook.com/X999/posts/Y999" - }, - { - "name": "Like", - "link": "http://www.facebook.com/X999/posts/Y999" - } - ], - "type": "status", - "created_time": "2010-08-02T21:27:44+0000", - "updated_time": "2010-08-02T21:27:44+0000" - }, - { - "id": "X998_Y998", - "from": { - "name": "Peyton Manning", "id": "X18" - }, - "message": "Where's my contract?", - "actions": [ - { - "name": "Comment", - "link": "http://www.facebook.com/X998/posts/Y998" - }, - { - "name": "Like", - "link": "http://www.facebook.com/X998/posts/Y998" - } - ], - "type": "status", - "created_time": "2010-08-02T21:27:44+0000", - "updated_time": "2010-08-02T21:27:44+0000" - } - ] -} diff --git a/test/json/flikr.json b/test/json/flikr.json deleted file mode 100644 index 710db0c71..000000000 --- a/test/json/flikr.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "title": "Talk On Travel Pool", - "link": "http://www.flickr.com/groups/talkontravel/pool/", - "description": "Travel and vacation photos from around the world.", - "modified": "2009-02-02T11:10:27Z", - "generator": "http://www.flickr.com/", - "items": [ - { - "title": "View from the hotel", - "link": "http://www.flickr.com/photos/33112458@N08/3081564649/in/pool-998875@N22", - "media": {"m":"http://farm4.static.flickr.com/3037/3081564649_4a6569750c_m.jpg"}, - "date_taken": "2008-12-04T04:43:03-08:00", - "description": "