diff --git a/Makefile b/Makefile index 5ef5431..3219f85 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ test-pre-clean: aggregate-results: $(TESTS) $(TESTS): test-pre-clean - -cd tests && sh $(notdir $@) $(TEST_OPTIONS) + -cd tests && ./$(notdir $@) $(TEST_OPTIONS) test: aggregate-results tests/aggregate-results.sh tests/test-results/t*-* diff --git a/tests/t1340-listescapes.sh b/tests/t1340-listescapes.sh new file mode 100755 index 0000000..075b9ec --- /dev/null +++ b/tests/t1340-listescapes.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# + +test_description='list with escape sequences + +This test checks listing of tasks that have embedded escape sequences in them. +' +. ./test-lib.sh + +# +# check aborted list output on \c escape sequence +# +cat > todo.txt <<'EOF' +first todo +second todo run C:\WINDOWS\sysnative\cscript.exe +third todo +EOF + +test_todo_session 'aborted list output on backslash-c' <<'EOF' +>>> todo.sh ls +1 first todo +2 second todo run C:\WINDOWS\sysnative\cscript.exe +3 third todo +-- +TODO: 3 of 3 tasks shown + +>>> todo.sh ls 2 +2 second todo run C:\WINDOWS\sysnative\cscript.exe +-- +TODO: 1 of 3 tasks shown +EOF + +# +# check various escape sequences +# +cat > todo.txt <<'EOF' +first todo with \\, \a and \t +second todo with \r\n line break +third todo with \x42\x55\x47 and \033[0;31m color codes \033[0;30m +EOF + +test_todo_session 'various escape sequences' <<'EOF' +>>> todo.sh ls +1 first todo with \\, \a and \t +2 second todo with \r\n line break +3 third todo with \x42\x55\x47 and \033[0;31m color codes \033[0;30m +-- +TODO: 3 of 3 tasks shown +EOF + +# +# check embedding of actual color sequence +# +cat > todo.txt <<'EOF' +A task with  actual color  +EOF + +test_todo_session 'embedding of actual color sequence' <<'EOF' +>>> todo.sh ls +1 A task with  actual color  +-- +TODO: 1 of 1 tasks shown +EOF + +test_done diff --git a/tests/t8000-actions.sh b/tests/t8000-actions.sh index 3d92248..03a1fbe 100755 --- a/tests/t8000-actions.sh +++ b/tests/t8000-actions.sh @@ -8,10 +8,27 @@ This test covers the contract between todo.sh and custom actions. unset TODO_ACTIONS_DIR mkdir .todo.actions.d -cat > .todo.actions.d/foo << EOF -echo "TODO: foo" +make_action() +{ + cat > ".todo.actions.d/$1" <<- EOF + #!/bin/bash + echo "custom action $1" +EOF +chmod +x ".todo.actions.d/$1" +} + +make_action "foo" +test_todo_session 'executable action' <>> todo.sh foo +custom action foo EOF +chmod -x .todo.actions.d/foo +# On Cygwin, clearing the executable flag may have no effect, as the Windows ACL +# may still grant execution rights. In this case, we skip the test. +if [ -x .todo.actions.d/foo ]; then + SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8000.2" +fi test_todo_session 'nonexecutable action' <>> todo.sh foo Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] @@ -19,33 +36,21 @@ Try 'todo.sh -h' for more information. === 1 EOF -chmod +x .todo.actions.d/foo -test_todo_session 'executable action' <>> todo.sh foo -TODO: foo -EOF - -cat > .todo.actions.d/ls << EOF -echo "TODO: my ls" -EOF -chmod +x .todo.actions.d/ls +make_action "ls" test_todo_session 'overriding built-in action' <>> todo.sh ls -TODO: my ls +custom action ls >>> todo.sh command ls -- TODO: 0 of 0 tasks shown EOF -cat > .todo.actions.d/bad << EOF -echo "TODO: bad" -exit 42 -EOF -chmod +x .todo.actions.d/bad +make_action "bad" +echo "exit 42" >> .todo.actions.d/bad test_todo_session 'failing action' <>> todo.sh bad -TODO: bad +custom action bad === 42 EOF diff --git a/tests/test-lib.sh b/tests/test-lib.sh index efe8960..29f3246 100644 --- a/tests/test-lib.sh +++ b/tests/test-lib.sh @@ -12,8 +12,10 @@ done,*) *' --tee '*|*' --va'*) mkdir -p test-results BASE=test-results/$(basename "$0" .sh) - (TEST_TEE_STARTED=done ${SHELL-sh} "$0" "$@" 2>&1; - echo $? > $BASE.exit) | tee $BASE.out + ( + TEST_TEE_STARTED=done ${SHELL-sh} "$0" "$@" 2>&1; + echo $? > $BASE.exit + ) | tee $BASE.out test "$(cat $BASE.exit)" = 0 exit ;; @@ -395,7 +397,7 @@ test_done () { 0) say_color pass "passed all $msg" - # Clean up this test. + # Clean up this test. test -d "$remove_trash" && cd "$(dirname "$remove_trash")" && rm -rf "$(basename "$remove_trash")" @@ -434,8 +436,8 @@ test_init_todo () { root="$1" mkdir -p "$root" cd "$root" || error "Cannot setup todo dir in $root" - # Initialize the configuration file. Carefully quoted. - sed -e 's|TODO_DIR=.*$|TODO_DIR="'"$TEST_DIRECTORY/$test"'"|' $TEST_DIRECTORY/../todo.cfg > todo.cfg + # Initialize the configuration file. Carefully quoted. + sed -e 's|TODO_DIR=.*$|TODO_DIR="'"$TEST_DIRECTORY/$test"'"|' $TEST_DIRECTORY/../todo.cfg > todo.cfg # Install latest todo.sh mkdir bin @@ -527,7 +529,7 @@ test_todo_session () { cmd="" status=0 > expect - while read line + while read -r line do case $line in ">>> "*) @@ -552,7 +554,7 @@ test_todo_session () { fi ;; *) - echo $line >> expect + echo "$line" >> expect ;; esac done diff --git a/todo.sh b/todo.sh index 315987a..e04ed37 100755 --- a/todo.sh +++ b/todo.sh @@ -232,7 +232,7 @@ help() echo "" for action in "$TODO_ACTIONS_DIR"/* do - if [ -x "$action" ] + if [ -f "$action" -a -x "$action" ] then "$action" usage fi @@ -550,7 +550,7 @@ _addto() { if [ $TODOTXT_VERBOSE -gt 0 ]; then TASKNUM=$(sed -n '$ =' "$file") BASE=$(basename "$file") - PREFIX=$(echo ${BASE%%.[^.]*} | tr [a-z] [A-Z]) + PREFIX=$(echo ${BASE%%.[^.]*} | tr 'a-z' 'A-Z') echo "$TASKNUM $input" echo "${PREFIX}: $TASKNUM added." fi @@ -622,12 +622,12 @@ _list() { | grep -v "^[ 0-9]\+ *$" ) if [ "${filter_command}" ]; then - filtered_items=$(echo -ne "$items" | eval ${filter_command}) + filtered_items=$(echo -n "$items" | eval ${filter_command}) else filtered_items=$items fi filtered_items=$( - echo -ne "$filtered_items" \ + echo -n "$filtered_items" \ | sed ''' s/^ /00000/; s/^ /0000/; @@ -636,17 +636,22 @@ _list() { s/^ /0/; ''' \ | eval ${TODOTXT_SORT_COMMAND} \ - | sed ''' - /^[0-9]\{'$PADDING'\} x /s|^.*|'$COLOR_DONE'&'$DEFAULT'| - ''' \ - | awk '''{ - pos = match($0, /\([A-Z]\)/) - if( pos > 0 && match($0, /^[0-9]+ x /) != 1 ) { - clr=ENVIRON["PRI_" substr($0, pos+1, 1)] - str = ( clr ? clr : ENVIRON["PRI_X"] ) $0 ENVIRON["DEFAULT"] - gsub( /\\+033/, "\033", str) ; print str - } else { print } - }''' \ + | awk ''' + function highlight(colorVar, color) { + color = ENVIRON[colorVar] + gsub(/\\+033/, "\033", color) + return color + } + { + pos = match($0, /\([A-Z]\)/) + if (match($0, /^[0-9]+ x /)) { + print highlight("COLOR_DONE") $0 highlight("DEFAULT") + } else if (pos > 0) { + clr = highlight("PRI_" substr($0, pos+1, 1)) + print ( clr ? clr : highlight("PRI_X") ) $0 highlight("DEFAULT") + } else { print } + } + ''' \ | sed ''' s/'${HIDE_PRIORITY_SUBSTITUTION:-^}'//g s/'${HIDE_PROJECTS_SUBSTITUTION:-^}'//g @@ -654,13 +659,13 @@ _list() { ''' \ | eval ${TODOTXT_FINAL_FILTER} \ ) - echo -ne "$filtered_items${filtered_items:+\n}" + [ "$filtered_items" ] && echo "$filtered_items" if [ $TODOTXT_VERBOSE -gt 0 ]; then BASE=$(basename "$FILE") - PREFIX=$(echo ${BASE%%.[^.]*} | tr [a-z] [A-Z]) - NUMTASKS=$( echo -ne "$filtered_items" | sed -n '$ =' ) - TOTALTASKS=$( echo -ne "$items" | sed -n '$ =' ) + PREFIX=$(echo ${BASE%%.[^.]*} | tr 'a-z' 'A-Z') + NUMTASKS=$( echo -n "$filtered_items" | sed -n '$ =' ) + TOTALTASKS=$( echo -n "$items" | sed -n '$ =' ) echo "--" echo "${PREFIX}: ${NUMTASKS:-0} of ${TOTALTASKS:-0} tasks shown" @@ -877,7 +882,7 @@ case $action in now=`date '+%Y-%m-%d'` # remove priority once item is done sed -i.bak $item"s/^(.) //" "$TODO_FILE" - sed -i.bak $item"s|^|&x $now |" "$TODO_FILE" + sed -i.bak $item"s|^|x $now |" "$TODO_FILE" if [ $TODOTXT_VERBOSE -gt 0 ]; then newtodo=$(sed "$item!d" "$TODO_FILE") echo "$item $newtodo"