From e33603939b36631e9371b32abe2708941ee6eb20 Mon Sep 17 00:00:00 2001 From: Paul Roub Date: Sun, 8 Jan 2012 12:14:08 -0500 Subject: [PATCH 01/14] Fix typo in duplicate removal on archive, per discussion at http://tech.groups.yahoo.com/group/todotxt/message/3775 --- tests/t1900-archive.sh | 34 ++++++++++++++++++++++++++++++++++ todo.sh | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100755 tests/t1900-archive.sh diff --git a/tests/t1900-archive.sh b/tests/t1900-archive.sh new file mode 100755 index 0000000..5ac9316 --- /dev/null +++ b/tests/t1900-archive.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +test_description='archive functionality + +Ensure we can append items successfully. +' +. ./test-lib.sh + +cat >> todo.txt<>> todo.sh archive +x done +TODO: $HOME/todo.txt archived. +EOF + +test_todo_session 'list after archive' <>> todo.sh ls +4 four +1 one +3 three +2 two +-- +TODO: 4 of 4 tasks shown +EOF + +test_done diff --git a/todo.sh b/todo.sh index 337bbea..f945fa6 100755 --- a/todo.sh +++ b/todo.sh @@ -371,7 +371,7 @@ archive() grep "^x " "$TODO_FILE" >> "$DONE_FILE" sed -i.bak '/^x /d' "$TODO_FILE" cp "$TODO_FILE" "$TMP_FILE" - sed -n 'G; s/\n/&&/; /^\([ ~-]*\n\).*\n\1/d; s/\n//; h; P' "$TMP_FILE" > "$TODO_FILE" + sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P' "$TMP_FILE" > "$TODO_FILE" if [ $TODOTXT_VERBOSE -gt 0 ]; then echo "TODO: $TODO_FILE archived." fi From 62d78a003482a4c4463b0f3ebd2bf5568fe2338f Mon Sep 17 00:00:00 2001 From: Paul Roub Date: Mon, 9 Jan 2012 10:34:05 -0500 Subject: [PATCH 02/14] explained the sed duplicate-removal pattern --- tests/t1900-archive.sh | 2 +- todo.sh | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/t1900-archive.sh b/tests/t1900-archive.sh index 5ac9316..630359b 100755 --- a/tests/t1900-archive.sh +++ b/tests/t1900-archive.sh @@ -2,7 +2,7 @@ test_description='archive functionality -Ensure we can append items successfully. +Ensure we can archive items successfully. ' . ./test-lib.sh diff --git a/todo.sh b/todo.sh index f945fa6..b817735 100755 --- a/todo.sh +++ b/todo.sh @@ -371,6 +371,19 @@ archive() grep "^x " "$TODO_FILE" >> "$DONE_FILE" sed -i.bak '/^x /d' "$TODO_FILE" cp "$TODO_FILE" "$TMP_FILE" + # look for duplicate lines with printable chars (i.e. duplicate tasks) + # and discard the second occurrence + # we start with an empty hold space on the first line. For each line: + # G - appends newline + hold space to the pattern space + # s/\n/&&/; - double up the first new line so we catch adjacent dups + # /^\([ -~]*\n\).*\n\1/d; + # If the first line (i.e. the new input line) of the hold space + # is printable, and if that same pattern shows up again later as + # an entire line, it's a duplicate. Delete the current pattern space, + # quit this line and move on to the next + # s/\n//; - else, drop the doubled newline + # h; - replace the hold space with the expanded pattern space + # P; - print up to the first newline (that is, the input line) sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P' "$TMP_FILE" > "$TODO_FILE" if [ $TODOTXT_VERBOSE -gt 0 ]; then echo "TODO: $TODO_FILE archived." From bf2ca0ed6ae68cd204cffd384709f8332c2056dc Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Fri, 13 Jan 2012 22:31:08 +0100 Subject: [PATCH 03/14] Rework fixed archive deduplication into new deduplicate action. As per discussion on the mailing list (http://tech.groups.yahoo.com/group/todotxt/message/3775), the automatic deduplication during archiving is unexpected and difficult to enforce in other implementations. Rather, make this a separate (optional) action. --- tests/t1900-archive.sh | 7 +++--- tests/t1910-deduplicate.sh | 38 ++++++++++++++++++++++++++++++++ todo.sh | 44 +++++++++++++++++++++++++------------- 3 files changed, 71 insertions(+), 18 deletions(-) create mode 100755 tests/t1910-deduplicate.sh diff --git a/tests/t1900-archive.sh b/tests/t1900-archive.sh index 630359b..9cc3ae6 100755 --- a/tests/t1900-archive.sh +++ b/tests/t1900-archive.sh @@ -6,7 +6,7 @@ Ensure we can archive items successfully. ' . ./test-lib.sh -cat >> todo.txt< todo.txt <>> todo.sh ls -4 four +5 four 1 one +4 one 3 three 2 two -- -TODO: 4 of 4 tasks shown +TODO: 5 of 5 tasks shown EOF test_done diff --git a/tests/t1910-deduplicate.sh b/tests/t1910-deduplicate.sh new file mode 100755 index 0000000..425418a --- /dev/null +++ b/tests/t1910-deduplicate.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +test_description='deduplicate functionality + +Ensure we can deduplicate items successfully. +' +. ./test-lib.sh + +cat >> todo.txt<>> todo.sh deduplicate +TODO: 2 duplicate task(s) removed + +>>> todo.sh -p ls +4 double task +1 duplicated +5 three +2 two +3 x done +-- +TODO: 5 of 5 tasks shown +EOF + +test_todo_session 'deduplicate without duplicates' <>> todo.sh deduplicate +TODO: No duplicate tasks found +EOF + +test_done diff --git a/todo.sh b/todo.sh index b817735..4a6dde7 100755 --- a/todo.sh +++ b/todo.sh @@ -50,6 +50,7 @@ shorthelp() append|app ITEM# "TEXT TO APPEND" archive command [ACTIONS] + deduplicate del|rm ITEM# [TERM] depri|dp ITEM#[, ITEM#, ITEM#, ...] do ITEM#[, ITEM#, ITEM#, ...] @@ -181,6 +182,9 @@ help() Runs the remaining arguments using only todo.sh builtins. Will not call any .todo.actions.d scripts. + deduplicate + Removes duplicate lines from todo.txt. + del ITEM# [TERM] rm ITEM# [TERM] Deletes the task on line ITEM# in todo.txt. @@ -370,21 +374,6 @@ archive() [ $TODOTXT_VERBOSE -gt 0 ] && grep "^x " "$TODO_FILE" grep "^x " "$TODO_FILE" >> "$DONE_FILE" sed -i.bak '/^x /d' "$TODO_FILE" - cp "$TODO_FILE" "$TMP_FILE" - # look for duplicate lines with printable chars (i.e. duplicate tasks) - # and discard the second occurrence - # we start with an empty hold space on the first line. For each line: - # G - appends newline + hold space to the pattern space - # s/\n/&&/; - double up the first new line so we catch adjacent dups - # /^\([ -~]*\n\).*\n\1/d; - # If the first line (i.e. the new input line) of the hold space - # is printable, and if that same pattern shows up again later as - # an entire line, it's a duplicate. Delete the current pattern space, - # quit this line and move on to the next - # s/\n//; - else, drop the doubled newline - # h; - replace the hold space with the expanded pattern space - # P; - print up to the first newline (that is, the input line) - sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P' "$TMP_FILE" > "$TODO_FILE" if [ $TODOTXT_VERBOSE -gt 0 ]; then echo "TODO: $TODO_FILE archived." fi @@ -1246,6 +1235,31 @@ note: PRIORITY must be anywhere from A to Z." cat "$REPORT_FILE" ;; +"deduplicate" ) + originalTaskNum=$( sed -n '$ =' "$TODO_FILE" ) + + # Look for duplicate lines and discard the second occurrence. + # We start with an empty hold space on the first line. For each line: + # G - appends newline + hold space to the pattern space + # s/\n/&&/; - double up the first new line so we catch adjacent dups + # /^\([ -~]*\n\).*\n\1/d; + # If the first line (i.e. the new input line) of the hold space + # is printable, and if that same pattern shows up again later as + # an entire line, it's a duplicate. Delete the current pattern space, + # quit this line and move on to the next + # s/\n//; - else, drop the doubled newline + # h; - replace the hold space with the expanded pattern space + # P; - print up to the first newline (that is, the input line) + sed -i.bak -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P' "$TODO_FILE" + newTaskNum=$( sed -n '$ =' "$TODO_FILE" ) + deduplicateNum=$(( originalTaskNum - newTaskNum )) + if [ $deduplicateNum -eq 0 ]; then + echo "TODO: No duplicate tasks found" + else + echo "TODO: $deduplicateNum duplicate task(s) removed" + fi + ;; + * ) usage;; esac From fe5cdcb13ab70d76f47f9de61ef35e9f314ec22c Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Fri, 13 Jan 2012 22:44:35 +0100 Subject: [PATCH 04/14] Fix deduplicate for non-printable (and non-ASCII) characters. --- tests/t1910-deduplicate.sh | 22 +++++++++++++++++++++- todo.sh | 9 ++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/t1910-deduplicate.sh b/tests/t1910-deduplicate.sh index 425418a..16dc999 100755 --- a/tests/t1910-deduplicate.sh +++ b/tests/t1910-deduplicate.sh @@ -6,7 +6,7 @@ Ensure we can deduplicate items successfully. ' . ./test-lib.sh -cat >> todo.txt< todo.txt < todo.txt <>> todo.sh deduplicate +TODO: 1 duplicate task(s) removed + +>>> todo.sh -p ls +2 a bold action +1 normal task +3 something else +4 something more +-- +TODO: 4 of 4 tasks shown +EOF + test_done diff --git a/todo.sh b/todo.sh index 4a6dde7..e2a3056 100755 --- a/todo.sh +++ b/todo.sh @@ -1242,15 +1242,14 @@ note: PRIORITY must be anywhere from A to Z." # We start with an empty hold space on the first line. For each line: # G - appends newline + hold space to the pattern space # s/\n/&&/; - double up the first new line so we catch adjacent dups - # /^\([ -~]*\n\).*\n\1/d; - # If the first line (i.e. the new input line) of the hold space - # is printable, and if that same pattern shows up again later as - # an entire line, it's a duplicate. Delete the current pattern space, + # /^\([^\n]*\n\).*\n\1/d; + # If the first line of the hold space shows up again later as an + # entire line, it's a duplicate. Delete the current pattern space, # quit this line and move on to the next # s/\n//; - else, drop the doubled newline # h; - replace the hold space with the expanded pattern space # P; - print up to the first newline (that is, the input line) - sed -i.bak -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P' "$TODO_FILE" + sed -i.bak -n 'G; s/\n/&&/; /^\([^\n]*\n\).*\n\1/d; s/\n//; h; P' "$TODO_FILE" newTaskNum=$( sed -n '$ =' "$TODO_FILE" ) deduplicateNum=$(( originalTaskNum - newTaskNum )) if [ $deduplicateNum -eq 0 ]; then From 6424c4c1a05da8e13222bd345527feeadf1d6635 Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Fri, 13 Jan 2012 23:27:58 +0100 Subject: [PATCH 05/14] Support "preserve line numbers" in deduplicate. --- tests/t1910-deduplicate.sh | 53 +++++++++++++++++++++++++++++++++++--- todo.sh | 24 ++++++++++++----- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/tests/t1910-deduplicate.sh b/tests/t1910-deduplicate.sh index 16dc999..567c235 100755 --- a/tests/t1910-deduplicate.sh +++ b/tests/t1910-deduplicate.sh @@ -16,10 +16,38 @@ double task three EOF -test_todo_session 'deduplicate with duplicates' <>> todo.sh deduplicate TODO: 2 duplicate task(s) removed +>>> todo.sh -p ls +5 double task +1 duplicated +7 three +2 two +3 x done +-- +TODO: 5 of 5 tasks shown +EOF + +test_todo_session 'deduplicate without duplicates' <>> todo.sh deduplicate +TODO: No duplicate tasks found +EOF + +cat > todo.txt <>> todo.sh -n deduplicate +TODO: 2 duplicate task(s) removed + >>> todo.sh -p ls 4 double task 1 duplicated @@ -30,9 +58,26 @@ TODO: 2 duplicate task(s) removed TODO: 5 of 5 tasks shown EOF -test_todo_session 'deduplicate without duplicates' < todo.txt <>> todo.sh deduplicate -TODO: No duplicate tasks found +TODO: 3 duplicate task(s) removed + +>>> todo.sh -p ls +2 duplicated +1 one +6 six +3 three +-- +TODO: 4 of 4 tasks shown EOF cat > todo.txt <> "$DONE_FILE" - sed -i.bak '/^x /d' "$TODO_FILE" - if [ $TODOTXT_VERBOSE -gt 0 ]; then - echo "TODO: $TODO_FILE archived." - fi -} - replaceOrPrepend() { action=$1; shift @@ -950,7 +938,15 @@ case $action in ;; "archive" ) - archive;; + # defragment blank lines + sed -i.bak -e '/./!d' "$TODO_FILE" + [ $TODOTXT_VERBOSE -gt 0 ] && grep "^x " "$TODO_FILE" + grep "^x " "$TODO_FILE" >> "$DONE_FILE" + sed -i.bak '/^x /d' "$TODO_FILE" + if [ $TODOTXT_VERBOSE -gt 0 ]; then + echo "TODO: $TODO_FILE archived." + fi + ;; "del" | "rm" ) # replace deleted line with a blank line when TODOTXT_PRESERVE_LINE_NUMBERS is 1 @@ -1052,7 +1048,9 @@ case $action in done if [ $TODOTXT_AUTO_ARCHIVE = 1 ]; then - archive + # Recursively invoke the script to allow overriding of the archive + # action. + "$TODO_FULL_SH" archive fi ;; @@ -1217,9 +1215,10 @@ note: PRIORITY must be anywhere from A to Z." ;; "report" ) - #archive first - sed '/^x /!d' "$TODO_FILE" >> "$DONE_FILE" - sed -i.bak '/^x /d' "$TODO_FILE" + # archive first + # Recursively invoke the script to allow overriding of the archive + # action. + "$TODO_FULL_SH" archive NUMLINES=$( sed -n '$ =' "$TODO_FILE" ) if [ ${NUMLINES:-0} = "0" ]; then From 88ac3d87e67c0389e47419f56fbe3a6bfe5ae50b Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Sat, 14 Jan 2012 14:41:58 +0100 Subject: [PATCH 07/14] Remove inactive broken report header. This was meant to write a report header on the initial report run, but as it mistakenly used TODO_FILE instead of REPORT_FILE, it was inactive, and also missing in the tests. Let's just remove it; the format is simple, anyway. --- todo.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/todo.sh b/todo.sh index 4929551..a9c619e 100755 --- a/todo.sh +++ b/todo.sh @@ -1220,11 +1220,6 @@ note: PRIORITY must be anywhere from A to Z." # action. "$TODO_FULL_SH" archive - NUMLINES=$( sed -n '$ =' "$TODO_FILE" ) - if [ ${NUMLINES:-0} = "0" ]; then - echo "datetime todos dones" >> "$REPORT_FILE" - fi - #now report TOTAL=$( sed -n '$ =' "$TODO_FILE" ) TDONE=$( sed -n '$ =' "$DONE_FILE" ) TECHO=$(echo $(date +%Y-%m-%d-%T); echo ' '; echo ${TOTAL:-0}; echo ' '; From ba66f66e8654f1d13c8463432560dd59ca533cdd Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Sat, 14 Jan 2012 14:56:03 +0100 Subject: [PATCH 08/14] Only print the added report line, not entire report. I think this makes much more sense, especially once the report gets very long. (One can always use "cat" to view the entire report.) --- tests/t9999-testsuite_example.sh | 16 +++++++++++++++- todo.sh | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/t9999-testsuite_example.sh b/tests/t9999-testsuite_example.sh index 9989fa9..18b93da 100755 --- a/tests/t9999-testsuite_example.sh +++ b/tests/t9999-testsuite_example.sh @@ -93,7 +93,6 @@ TODO: Report file updated. TODO: $HOME/todo.txt archived. TODO: Report file updated. 2009-02-13-04:40:00 5 1 -2009-02-13-04:40:00 5 1 >>> todo.sh append g a usage: todo.sh append ITEM# "TEXT TO APPEND" @@ -164,6 +163,21 @@ TODO: 6 of 6 tasks shown -- TODO: 6 of 6 tasks shown +>>> todo.sh -a do 3 +3 x 2009-02-13 smell the coffee +wakeup +TODO: 3 marked as done. + +>>> todo.sh report +x 2009-02-13 smell the coffee +wakeup +TODO: $HOME/todo.txt archived. +TODO: Report file updated. +2009-02-13-04:40:00 5 2 + +>>> todo.sh report +TODO: $HOME/todo.txt archived. +TODO: Report file updated. +2009-02-13-04:40:00 5 2 + >>> todo.sh remdup Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] Try 'todo.sh -h' for more information. diff --git a/todo.sh b/todo.sh index a9c619e..b8b476f 100755 --- a/todo.sh +++ b/todo.sh @@ -1226,7 +1226,7 @@ note: PRIORITY must be anywhere from A to Z." echo ${TDONE:-0}) echo $TECHO >> "$REPORT_FILE" [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file updated." - cat "$REPORT_FILE" + sed -ne '$p' "$REPORT_FILE" ;; "deduplicate" ) From 7a4d11812d34758ac3c51132a89ffe5fc4957804 Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Sat, 14 Jan 2012 14:58:58 +0100 Subject: [PATCH 09/14] Simplify writing of report line. --- todo.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/todo.sh b/todo.sh index b8b476f..83f2502 100755 --- a/todo.sh +++ b/todo.sh @@ -1222,9 +1222,7 @@ note: PRIORITY must be anywhere from A to Z." TOTAL=$( sed -n '$ =' "$TODO_FILE" ) TDONE=$( sed -n '$ =' "$DONE_FILE" ) - TECHO=$(echo $(date +%Y-%m-%d-%T); echo ' '; echo ${TOTAL:-0}; echo ' '; - echo ${TDONE:-0}) - echo $TECHO >> "$REPORT_FILE" + echo "$(date +%Y-%m-%d-%T) ${TOTAL:-0} ${TDONE:-0}" >> "$REPORT_FILE" [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file updated." sed -ne '$p' "$REPORT_FILE" ;; From d0205b48a682a61c425293d5fa0e49510e5c4989 Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Sat, 14 Jan 2012 15:04:55 +0100 Subject: [PATCH 10/14] Use ISO 8601 timestamp format. IMO 2012-01-14T14:49 looks better than the messy -*-*-*- of 2012-01-14-14:49, and is more aligned with standards. --- tests/t9999-testsuite_example.sh | 6 +++--- todo.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/t9999-testsuite_example.sh b/tests/t9999-testsuite_example.sh index 18b93da..7ca889e 100755 --- a/tests/t9999-testsuite_example.sh +++ b/tests/t9999-testsuite_example.sh @@ -92,7 +92,7 @@ TODO: Report file updated. >>> todo.sh report TODO: $HOME/todo.txt archived. TODO: Report file updated. -2009-02-13-04:40:00 5 1 +2009-02-13T04:40:00 5 1 >>> todo.sh append g a usage: todo.sh append ITEM# "TEXT TO APPEND" @@ -171,12 +171,12 @@ TODO: 3 marked as done. x 2009-02-13 smell the coffee +wakeup TODO: $HOME/todo.txt archived. TODO: Report file updated. -2009-02-13-04:40:00 5 2 +2009-02-13T04:40:00 5 2 >>> todo.sh report TODO: $HOME/todo.txt archived. TODO: Report file updated. -2009-02-13-04:40:00 5 2 +2009-02-13T04:40:00 5 2 >>> todo.sh remdup Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] diff --git a/todo.sh b/todo.sh index 83f2502..a37be5c 100755 --- a/todo.sh +++ b/todo.sh @@ -1222,7 +1222,7 @@ note: PRIORITY must be anywhere from A to Z." TOTAL=$( sed -n '$ =' "$TODO_FILE" ) TDONE=$( sed -n '$ =' "$DONE_FILE" ) - echo "$(date +%Y-%m-%d-%T) ${TOTAL:-0} ${TDONE:-0}" >> "$REPORT_FILE" + echo "$(date +%Y-%m-%dT%T) ${TOTAL:-0} ${TDONE:-0}" >> "$REPORT_FILE" [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file updated." sed -ne '$p' "$REPORT_FILE" ;; From d46adadb1d1336f50e7cac6a28c64d735fcdd2fe Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Sat, 14 Jan 2012 15:10:22 +0100 Subject: [PATCH 11/14] Align report order with other actions. Like "add" or "do", first the object, then (in verbose mode) the status message is printed. --- tests/t9999-testsuite_example.sh | 22 +--------------------- todo.sh | 2 +- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/tests/t9999-testsuite_example.sh b/tests/t9999-testsuite_example.sh index 7ca889e..0c7efbe 100755 --- a/tests/t9999-testsuite_example.sh +++ b/tests/t9999-testsuite_example.sh @@ -86,13 +86,8 @@ TODO: 5 of 5 tasks shown >>> todo.sh report TODO: $HOME/todo.txt archived. -TODO: Report file updated. -2009-02-13-04:40:00 5 1 - ->>> todo.sh report -TODO: $HOME/todo.txt archived. -TODO: Report file updated. 2009-02-13T04:40:00 5 1 +TODO: Report file updated. >>> todo.sh append g a usage: todo.sh append ITEM# "TEXT TO APPEND" @@ -163,21 +158,6 @@ TODO: 6 of 6 tasks shown -- TODO: 6 of 6 tasks shown ->>> todo.sh -a do 3 -3 x 2009-02-13 smell the coffee +wakeup -TODO: 3 marked as done. - ->>> todo.sh report -x 2009-02-13 smell the coffee +wakeup -TODO: $HOME/todo.txt archived. -TODO: Report file updated. -2009-02-13T04:40:00 5 2 - ->>> todo.sh report -TODO: $HOME/todo.txt archived. -TODO: Report file updated. -2009-02-13T04:40:00 5 2 - >>> todo.sh remdup Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] Try 'todo.sh -h' for more information. diff --git a/todo.sh b/todo.sh index a37be5c..6c34003 100755 --- a/todo.sh +++ b/todo.sh @@ -1223,8 +1223,8 @@ note: PRIORITY must be anywhere from A to Z." TOTAL=$( sed -n '$ =' "$TODO_FILE" ) TDONE=$( sed -n '$ =' "$DONE_FILE" ) echo "$(date +%Y-%m-%dT%T) ${TOTAL:-0} ${TDONE:-0}" >> "$REPORT_FILE" - [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file updated." sed -ne '$p' "$REPORT_FILE" + [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file updated." ;; "deduplicate" ) From 7e525ee7438d254526add0ae62d04225259b9b55 Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Sat, 14 Jan 2012 15:21:53 +0100 Subject: [PATCH 12/14] ENH: Only add new data to report. When the last reported values are identical to the current values, do not append the same information (just with a new timestamp) to the report. Instead, just print the last report line. With this, the report action can be scheduled periodically (e.g. via cron) without artificially inflating the report file. --- todo.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/todo.sh b/todo.sh index 6c34003..10b1246 100755 --- a/todo.sh +++ b/todo.sh @@ -1222,9 +1222,18 @@ note: PRIORITY must be anywhere from A to Z." TOTAL=$( sed -n '$ =' "$TODO_FILE" ) TDONE=$( sed -n '$ =' "$DONE_FILE" ) - echo "$(date +%Y-%m-%dT%T) ${TOTAL:-0} ${TDONE:-0}" >> "$REPORT_FILE" - sed -ne '$p' "$REPORT_FILE" - [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file updated." + NEWDATA="${TOTAL:-0} ${TDONE:-0}" + LASTREPORT=$(sed -ne '$p' "$REPORT_FILE") + LASTDATA=${LASTREPORT#* } # Strip timestamp. + if [ "$LASTDATA" = "$NEWDATA" ]; then + echo "$LASTREPORT" + [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file is up-to-date." + else + NEWREPORT="$(date +%Y-%m-%dT%T) ${NEWDATA}" + echo "${NEWREPORT}" >> "$REPORT_FILE" + echo "${NEWREPORT}" + [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file updated." + fi ;; "deduplicate" ) From 880d829e8e4182a923712bc2e5cdcfc9f677a38a Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Sat, 14 Jan 2012 21:48:48 +0100 Subject: [PATCH 13/14] Create dedicated test file for report tests. --- tests/t1950-report.sh | 96 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 tests/t1950-report.sh diff --git a/tests/t1950-report.sh b/tests/t1950-report.sh new file mode 100755 index 0000000..46bbf97 --- /dev/null +++ b/tests/t1950-report.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +test_description='report functionality + +This test checks the reporting and the format of the report file. +' +. ./test-lib.sh + +cat > todo.txt <>> todo.sh report +TODO: $HOME/todo.txt archived. +2009-02-13T04:40:00 5 0 +TODO: Report file updated. + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +4 make the coffee +wakeup +3 smell the coffee +wakeup +2 stop and think +5 visit http://example.com +-- +TODO: 5 of 5 tasks shown +EOF + +test_todo_session 'report of done tasks' <>> todo.sh -A do 3 +3 x 2009-02-13 smell the coffee +wakeup +TODO: 3 marked as done. +x 2009-02-13 smell the coffee +wakeup +TODO: $HOME/todo.txt archived. + +>>> todo.sh report +TODO: $HOME/todo.txt archived. +2009-02-13T04:40:00 4 1 +TODO: Report file updated. + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +3 make the coffee +wakeup +2 stop and think +4 visit http://example.com +-- +TODO: 4 of 4 tasks shown +EOF + +test_todo_session 'report performs archiving' <>> todo.sh -a do 3 +3 x 2009-02-13 make the coffee +wakeup +TODO: 3 marked as done. + +>>> todo.sh report +x 2009-02-13 make the coffee +wakeup +TODO: $HOME/todo.txt archived. +2009-02-13T04:40:00 3 2 +TODO: Report file updated. + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +2 stop and think +3 visit http://example.com +-- +TODO: 3 of 3 tasks shown + +>>> todo.sh -p listfile done.txt +2 x 2009-02-13 make the coffee +wakeup +1 x 2009-02-13 smell the coffee +wakeup +-- +DONE: 2 of 2 tasks shown +EOF + +test_todo_session 'report is unchanged when no changes' <>> cat report.txt +2009-02-13T04:40:00 5 0 +2009-02-13T04:40:00 4 1 +2009-02-13T04:40:00 3 2 + +>>> todo.sh report +TODO: $HOME/todo.txt archived. +2009-02-13T04:40:00 3 2 +TODO: Report file is up-to-date. + +>>> cat report.txt +2009-02-13T04:40:00 5 0 +2009-02-13T04:40:00 4 1 +2009-02-13T04:40:00 3 2 +EOF + +test_done From 25e6d7ae248aa66757f986cf1d44e755162673f1 Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Mon, 23 Jan 2012 11:05:12 +0100 Subject: [PATCH 14/14] FIX: Adapt deduplicate sed command for OS X. The sed command of BSD / OS X doesn't like { command } blocks in a single expression. So move the (dynamic) deduplicate sed command(s) to the end, and use a label to access them. This also makes the entire sed script somewhat easier to understand. --- tests/t1910-deduplicate.sh | 6 +++--- todo.sh | 26 +++++++++++++++++--------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/tests/t1910-deduplicate.sh b/tests/t1910-deduplicate.sh index 567c235..be225e8 100755 --- a/tests/t1910-deduplicate.sh +++ b/tests/t1910-deduplicate.sh @@ -82,9 +82,9 @@ EOF cat > todo.txt <>> todo.sh -p ls -2 a bold action +2 a bold task 1 normal task 3 something else 5 something more diff --git a/todo.sh b/todo.sh index 10b1246..2c03377 100755 --- a/todo.sh +++ b/todo.sh @@ -1240,7 +1240,7 @@ note: PRIORITY must be anywhere from A to Z." if [ $TODOTXT_PRESERVE_LINE_NUMBERS = 0 ]; then deduplicateSedCommand='d' else - deduplicateSedCommand='{ s/^.*//; p; b }' + deduplicateSedCommand='s/^.*//; p' fi # To determine the difference when deduplicated lines are preserved, only @@ -1251,17 +1251,25 @@ note: PRIORITY must be anywhere from A to Z." # We start with an empty hold space on the first line. For each line: # G - appends newline + hold space to the pattern space # s/\n/&&/; - double up the first new line so we catch adjacent dups - # /^\([^\n]*\n\).*\n\1/ + # /^\([^\n]*\n\).*\n\1/b dedup # If the first line of the hold space shows up again later as an - # entire line, it's a duplicate. - # d; - Delete the current pattern space, quit this line - # and move on to the next, or: - # { s/^.*//; p; b }; - Clear the task text, print this line and move on - # to the next. - # s/\n//; - else, drop the doubled newline + # entire line, it's a duplicate. Jump to the "dedup" label, where + # either of the following is executed, depending on whether empty + # lines should be preserved: + # d - Delete the current pattern space, quit this line and + # move on to the next, or: + # s/^.*//; p - Clear the task text, print this line and move on to + # the next. + # s/\n//; - else (no duplicate), drop the doubled newline # h; - replace the hold space with the expanded pattern space # P; - print up to the first newline (that is, the input line) - sed -i.bak -n 'G; s/\n/&&/; /^\([^\n]*\n\).*\n\1/'"$deduplicateSedCommand"'; s/\n//; h; P' "$TODO_FILE" + # b - end processing of the current line + sed -i.bak -n \ + -e 'G; s/\n/&&/; /^\([^\n]*\n\).*\n\1/b dedup' \ + -e 's/\n//; h; P; b' \ + -e ':dedup' \ + -e "$deduplicateSedCommand" \ + "$TODO_FILE" newTaskNum=$( sed -e '/./!d' "$TODO_FILE" | sed -n '$ =' ) deduplicateNum=$(( originalTaskNum - newTaskNum ))