diff --git a/tests/t1100-replace.sh b/tests/t1100-replace.sh index e796052..a9f489f 100755 --- a/tests/t1100-replace.sh +++ b/tests/t1100-replace.sh @@ -77,6 +77,7 @@ replaced with replaced with 4: (A) collect the eggs EOF + test_todo_session 'replace with &' << EOF >>> todo.sh replace 3 "thrash the hay & thresh the wheat" 3: jump on hay @@ -90,4 +91,44 @@ test_todo_session 'replace error' << EOF 10: No such task. EOF +cat /dev/null > todo.txt +test_todo_session 'replace handling prepended date on add' <>> todo.sh -t add "new task" +1: 2009-02-13 new task +TODO: 1 added. + +>>> todo.sh replace 1 this is just a new one +1: 2009-02-13 new task +replaced with +1: 2009-02-13 this is just a new one + +>>> todo.sh replace 1 2010-07-04 this also has a new date +1: 2009-02-13 this is just a new one +replaced with +1: 2010-07-04 this also has a new date +EOF + +cat /dev/null > todo.txt +test_todo_session 'replace handling priority and prepended date on add' <>> todo.sh -t add "new task" +1: 2009-02-13 new task +TODO: 1 added. + +>>> todo.sh pri 1 A +1: (A) 2009-02-13 new task +TODO: 1 prioritized (A). + +>>> todo.sh replace 1 this is just a new one +1: (A) 2009-02-13 new task +replaced with +1: (A) 2009-02-13 this is just a new one +EOF + +test_todo_session 'replace with prepended date replaces existing date' <>> todo.sh replace 1 2010-07-04 this also has a new date +1: (A) 2009-02-13 this is just a new one +replaced with +1: (A) 2010-07-04 this also has a new date +EOF + test_done diff --git a/tests/t1400-prepend.sh b/tests/t1400-prepend.sh index 5a19c0b..4219b09 100755 --- a/tests/t1400-prepend.sh +++ b/tests/t1400-prepend.sh @@ -57,4 +57,38 @@ test_todo_session 'prepend with &' < todo.txt +test_todo_session 'prepend handling prepended date on add' <>> todo.sh -t add "new task" +1: 2009-02-13 new task +TODO: 1 added. + +>>> todo.sh prepend 1 "this is just a" +1: 2009-02-13 this is just a new task +EOF + +cat /dev/null > todo.txt +test_todo_session 'prepend handling priority and prepended date on add' <>> todo.sh -t add "new task" +1: 2009-02-13 new task +TODO: 1 added. + +>>> todo.sh pri 1 A +1: (A) 2009-02-13 new task +TODO: 1 prioritized (A). + +>>> todo.sh prepend 1 "this is just a" +1: (A) 2009-02-13 this is just a new task +EOF + +cat /dev/null > todo.txt +test_todo_session 'prepend with prepended date keeps both' <>> todo.sh -t add "new task" +1: 2009-02-13 new task +TODO: 1 added. + +>>> todo.sh prepend 1 "2010-07-04 this is just a" +1: 2009-02-13 2010-07-04 this is just a new task +EOF + test_done diff --git a/tests/t1600-append.sh b/tests/t1600-append.sh index 885074e..57ee99e 100755 --- a/tests/t1600-append.sh +++ b/tests/t1600-append.sh @@ -44,4 +44,33 @@ test_todo_session 'append error' << EOF 10: No such task. EOF +cat > todo.txt <>> todo.sh append 1 ", lilies and roses" +1: notice the daisies, lilies and roses + +>>> todo.sh append 1 "; see the wasps" +1: notice the daisies, lilies and roses; see the wasps + +>>> todo.sh append 1 "& bees" +1: notice the daisies, lilies and roses; see the wasps & bees +EOF + +cp todo.cfg special-delimiters.cfg +cat >> special-delimiters.cfg <>> todo.sh -d special-delimiters.cfg append 1 "&beans" +1: notice the daisies, lilies and roses; see the wasps & bees&beans + +>>> todo.sh -d special-delimiters.cfg append 1 "%foo" +1: notice the daisies, lilies and roses; see the wasps & bees&beans %foo + +>>> todo.sh -d special-delimiters.cfg append 1 "*2" +1: notice the daisies, lilies and roses; see the wasps & bees&beans %foo*2 +EOF + test_done diff --git a/todo.sh b/todo.sh index d2fc5de..20dc20e 100755 --- a/todo.sh +++ b/todo.sh @@ -1,5 +1,8 @@ #! /bin/bash +# === HEAVY LIFTING === +shopt -s extglob + # NOTE: Todo.sh requires the .todo/config configuration file to run. # Place the .todo/config file in your home directory or use the -d option for a custom location. @@ -281,6 +284,63 @@ archive() [ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: $TODO_FILE archived." } +replaceOrPrepend() +{ + action=$1; shift + case "$action" in + replace) + backref= + querytext="Replacement: " + ;; + prepend) + backref=' &' + querytext="Prepend: " + ;; + esac + shift; item=$1; shift + + [ -z "$item" ] && die "$errmsg" + [[ "$item" = +([0-9]) ]] || die "$errmsg" + + todo=$(sed "$item!d" "$TODO_FILE") + [ -z "$todo" ] && die "$item: No such task." + + if [[ -z "$1" && $TODOTXT_FORCE = 0 ]]; then + echo -n "$querytext" + read input + else + input=$* + fi + cleaninput $input + + # Retrieve existing priority and prepended date + priority=$(sed -e "$item!d" -e $item's/^\(([A-Z]) \)\{0,1\}\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{0,1\}.*/\1/' "$TODO_FILE") + prepdate=$(sed -e "$item!d" -e $item's/^\(([A-Z]) \)\{0,1\}\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{0,1\}.*/\2/' "$TODO_FILE") + + if [ "$prepdate" -a "$action" = "replace" ] && [ "$(echo "$input"|sed -e 's/^\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\}\)\{0,1\}.*/\1/')" ]; then + # If the replaced text starts with a date, it will replace the existing + # date, too. + prepdate= + fi + + # Temporarily remove any existing priority and prepended date, perform the + # change (replace/prepend) and re-insert the existing priority and prepended + # date again. + sed -i.bak -e "$item s/^${priority}${prepdate}//" -e "$item s|^.*|${priority}${prepdate}${input}${backref}|" "$TODO_FILE" + if [ $TODOTXT_VERBOSE -gt 0 ]; then + newtodo=$(sed "$item!d" "$TODO_FILE") + case "$action" in + replace) + echo "$item: $todo" + echo "replaced with" + echo "$item: $newtodo" + ;; + prepend) + echo "$item: $newtodo" + ;; + esac + fi +} # == PROCESS OPTIONS == while getopts ":fhpnatvVx+@Pd:" Option @@ -409,6 +469,12 @@ export PRI_B=$GREEN # color for B priority export PRI_C=$LIGHT_BLUE # color for C priority export PRI_X=$WHITE # color for rest of them +# Default sentence delimiters for todo.sh append. +# If the text to be appended to the task begins with one of these characters, no +# whitespace is inserted in between. This makes appending to an enumeration +# (todo.sh add 42 ", foo") syntactically correct. +export SENTENCE_DELIMITERS=',.:;' + [ -e "$TODOTXT_CFG_FILE" ] || { CFG_FILE_ALT="$HOME/todo.cfg" @@ -466,9 +532,6 @@ if [ $TODOTXT_PLAIN = 1 ]; then DEFAULT=$NONE fi -# === HEAVY LIFTING === -shopt -s extglob - _addto() { file="$1" input="$2" @@ -689,9 +752,13 @@ case $action in else input=$* fi + case "$input" in + [$SENTENCE_DELIMITERS]*) appendspace=;; + *) appendspace=" ";; + esac cleaninput $input - if sed -i.bak $item" s|^.*|& $input|" "$TODO_FILE"; then + if sed -i.bak $item" s|^.*|&${appendspace}${input}|" "$TODO_FILE"; then [ $TODOTXT_VERBOSE -gt 0 ] && { newtodo=$(sed "$item!d" "$TODO_FILE") echo "$item: $newtodo" @@ -914,48 +981,7 @@ case $action in "prepend" | "prep" ) errmsg="usage: $TODO_SH prepend ITEM# \"TEXT TO PREPEND\"" - shift; item=$1; shift - - [ -z "$item" ] && die "$errmsg" - [[ "$item" = +([0-9]) ]] || die "$errmsg" - - todo=$(sed "$item!d" "$TODO_FILE") - [ -z "$todo" ] && die "$item: No such task." - - if [[ -z "$1" && $TODOTXT_FORCE = 0 ]]; then - echo -n "Prepend: " - read input - else - input=$* - fi - cleaninput $input - - # Test for then set priority - if [ `sed "$item!d" "$TODO_FILE"|grep -c "^(\\w)"` -eq 1 ]; then - priority=$(sed "$item!d" "$TODO_FILE" | awk -F '\\(|\\)' '{print $2}') - fi - - # If priority isn't set prepend - if [ -z $priority ]; then - if sed -i.bak $item" s|^.*|$input &|" "$TODO_FILE"; then - [ $TODOTXT_VERBOSE -gt 0 ] && { - newtodo=$(sed "$item!d" "$TODO_FILE") - echo "$item: $newtodo" - } - else - echo "TODO: Error prepending task $item." - fi - # If priority is set, remove priority, prepend and add back priority - else - if sed -i.bak -e "$item s/^(.) //" -e "$item s|^.*|\($priority\) $1 &|" "$TODO_FILE"; then - [ $TODOTXT_VERBOSE -gt 0 ] && { - newtodo=$(sed "$item!d" "$TODO_FILE") - echo "$item: $newtodo" - } - else - echo "TODO: Error prepending task $item." - fi - fi + replaceOrPrepend 'prepend' "$@" ;; "pri" | "p" ) @@ -986,39 +1012,7 @@ note: PRIORITY must be anywhere from A to Z." "replace" ) errmsg="usage: $TODO_SH replace ITEM# \"UPDATED ITEM\"" - shift; item=$1; shift - - [ -z "$item" ] && die "$errmsg" - [[ "$item" = +([0-9]) ]] || die "$errmsg" - - todo=$(sed "$item!d" "$TODO_FILE") - [ -z "$todo" ] && die "$item: No such task." - - # Test for then set priority - if [ `sed "$item!d" "$TODO_FILE"|grep -c "^(\\w)"` -eq 1 ]; then - priority=$(sed "$item!d" "$TODO_FILE" | awk -F '\\(|\\)' '{print $2}') - fi - - if [[ -z "$1" && $TODOTXT_FORCE = 0 ]]; then - echo -n "Replacement: " - read input - else - input=$* - fi - cleaninput $input - - # If priority isn't set replace, if it is remove priority, replace then add priority again - if [ -z $priority ]; then - sed -i.bak $item" s|^.*|$input|" "$TODO_FILE" - else - sed -i.bak -e "$item s/^(.) //" -e "$item s|^.*|\($priority\) $input|" "$TODO_FILE" - fi - [ $TODOTXT_VERBOSE -gt 0 ] && { - NEWTODO=$(head -$item "$TODO_FILE" | tail -1) - echo "$item: $todo" - echo "replaced with" - echo "$item: $NEWTODO" - } + replaceOrPrepend 'replace' "$@" ;; "report" )