Compare commits

..

6 Commits

Author SHA1 Message Date
Ingo Karkat
56bd927747 Consistency: Also use /[A-Z]/ instead of /[[:upper:]]/.
Aligning the single outlier with the common usage.
2011-05-10 14:40:38 +02:00
Ingo Karkat
8f92cb6f66 Consistency: Use /(.)/ as generic pattern for priority in replaceOrPrepend().
Even though Gina's todo.txt syntax reference only mentions uppercase A-Z priorities, this is handled in two different ways in the code. I think the following guideline is useful: For a user-supplied priority (in the listpri and pri commands), use a strict check for A-Z. In general list and edit operations that need to be aware of the optional priority at the beginning of a task, use the general /^(.) / regexp. This allows addons to use different priority-like markers (e.g. "(-) no do"), have them ignored as priorities, but still maintained by replacements.
2011-05-10 13:04:53 +02:00
Ingo Karkat
e6136e14b8 pri: Check for existing priority and adapt message.
The existing check (as with depri) didn't do much good. Instead, fetch the existing priority and use that information to print more specific messages:
- TODO: 42 re-prioritized from (C) to (A)
- TODO: 42 already prioritized (A)
2011-05-10 12:44:34 +02:00
Ingo Karkat
5605c4b1b9 Split off reprioritization from pri test. 2011-05-10 12:17:39 +02:00
Ingo Karkat
c6467d90aa Cosmetics: Add TODO: prefix to todo.txt do message on already done task. 2011-05-10 12:07:50 +02:00
Ingo Karkat
ddd3e9711b depri: Check for unprioritized task and print message.
The existing check didn't do much good, and one could deprioritize any normal task without notice. Instead, check that the task to be deprioritized actually has a priority and alert via "TODO: 42 is not prioritized." if that is not the case.
2011-05-10 11:52:38 +02:00
11 changed files with 93 additions and 422 deletions

View File

@@ -1,16 +0,0 @@
#!/bin/sh
test_description='no old-style backtick command substitution
This test checks the todo.sh script itself for occurrences
of old-style backtick command substitution, which should be
replaced with $(...).
On failure, it will print each offending line number and line.
'
. ./test-lib.sh
test_todo_session 'no old-style backtick command substitution' <<EOF
>>> sed -n -e 's/\(^\|[ \t]\)#.*//' -e '/\`/{' -e '=;p' -e '}' "$(which todo.sh)"
EOF
test_done

View File

@@ -77,37 +77,4 @@ TODO: 5 added.
TODO: 5 of 5 tasks shown
EOF
#
# Advanced add
#
cat /dev/null > todo.txt
test_todo_session 'add with spaces' <<EOF
>>> todo.sh add "notice the three spaces"
1 notice the three spaces
TODO: 1 added.
>>> todo.sh add notice how the spaces get lost
2 notice how the spaces get lost
TODO: 2 added.
>>> todo.sh list
2 notice how the spaces get lost
1 notice the three spaces
--
TODO: 2 of 2 tasks shown
EOF
cat /dev/null > todo.txt
test_todo_session 'add with CR' <<EOF
>>> todo.sh add "smell the
Carriage Return"
1 smell the Carriage Return
TODO: 1 added.
>>> todo.sh list
1 smell the Carriage Return
--
TODO: 1 of 1 tasks shown
EOF
test_done

View File

@@ -21,22 +21,6 @@ TODO: 1 added.
TODO: 1 of 1 tasks shown
EOF
test_todo_session 'cmd line first day with priority' <<EOF
>>> todo.sh -pt add '(A) notice the daisies'
2 (A) 2009-02-13 notice the daisies
TODO: 2 added.
>>> todo.sh -p list
2 (A) 2009-02-13 notice the daisies
1 2009-02-13 notice the daisies
--
TODO: 2 of 2 tasks shown
>>> todo.sh -npf del 2
2 (A) 2009-02-13 notice the daisies
TODO: 2 deleted.
EOF
test_tick
test_todo_session 'cmd line second day' <<EOF

View File

@@ -45,12 +45,6 @@ grow some corn
thrash some hay
chase the chickens
EOF
test_todo_session 'replace error' << EOF
>>> todo.sh replace 10 "hej!"
=== 1
TODO: No task 10.
EOF
test_todo_session 'replace in multi-item file' <<EOF
>>> todo.sh replace 1 smell the cheese
1 smell the cows
@@ -68,59 +62,33 @@ TODO: Replaced task with:
4 collect the eggs
EOF
echo '(A) collect the eggs' > todo.txt
test_todo_session 'replace with priority' <<EOF
>>> todo.sh replace 1 "collect the bread"
1 (A) collect the eggs
TODO: Replaced task with:
1 (A) collect the bread
>>> todo.sh pri 4 a
4 (A) collect the eggs
TODO: 4 prioritized (A).
>>> todo.sh replace 1 collect the eggs
1 (A) collect the bread
>>> todo.sh replace 4 "collect the bread"
4 (A) collect the eggs
TODO: Replaced task with:
1 (A) collect the eggs
4 (A) collect the bread
>>> todo.sh replace 4 collect the eggs
4 (A) collect the bread
TODO: Replaced task with:
4 (A) collect the eggs
EOF
echo 'jump on hay' > todo.txt
test_todo_session 'replace with &' << EOF
>>> todo.sh replace 1 "thrash the hay & thrash the wheat"
1 jump on hay
>>> todo.sh replace 3 "thrash the hay & thresh the wheat"
3 jump on hay
TODO: Replaced task with:
1 thrash the hay & thrash the wheat
3 thrash the hay & thresh the wheat
EOF
echo 'jump on hay' > todo.txt
test_todo_session 'replace with spaces' <<EOF
>>> todo.sh replace 1 "notice the three spaces"
1 jump on hay
TODO: Replaced task with:
1 notice the three spaces
EOF
cat > todo.txt <<EOF
smell the cows
grow some corn
thrash some hay
chase the chickens
EOF
test_todo_session 'replace with symbols' <<EOF
>>> todo.sh replace 1 "~@#$%^&*()-_=+[{]}|;:',<.>/?"
1 smell the cows
TODO: Replaced task with:
1 ~@#$%^&*()-_=+[{]}|;:',<.>/?
>>> todo.sh replace 2 '\`!\\"'
2 grow some corn
TODO: Replaced task with:
2 \`!\\"
>>> todo.sh list
4 chase the chickens
3 thrash some hay
2 \`!\\"
1 ~@#$%^&*()-_=+[{]}|;:',<.>/?
--
TODO: 4 of 4 tasks shown
test_todo_session 'replace error' << EOF
>>> todo.sh replace 10 "hej!"
=== 1
TODO: No task 10.
EOF
cat /dev/null > todo.txt
@@ -156,7 +124,6 @@ TODO: Replaced task with:
1 (A) 2009-02-13 this is just a new one
EOF
echo '(A) 2009-02-13 this is just a new one' > todo.txt
test_todo_session 'replace with prepended date replaces existing date' <<EOF
>>> todo.sh replace 1 2010-07-04 this also has a new date
1 (A) 2009-02-13 this is just a new one

View File

@@ -87,11 +87,10 @@ TODO: 3 of 3 tasks shown
2 (A) notice the sunflowers
TODO: 2 already prioritized (A).
>>> todo.sh -p list
>>> todo.sh -p listpri
2 (A) notice the sunflowers
1 (B) smell the uppercase Roses +flowers @outside
3 stop
--
TODO: 3 of 3 tasks shown
TODO: 2 of 3 tasks shown
EOF
test_done

View File

@@ -1,95 +0,0 @@
#!/bin/sh
test_description='list priority functionality
'
. ./test-lib.sh
cat > todo.txt <<EOF
(B) smell the uppercase Roses +flowers @outside
(C) notice the sunflowers
stop
EOF
test_todo_session 'basic listpri' <<EOF
>>> todo.sh listpri A
--
TODO: 0 of 3 tasks shown
>>> todo.sh -p listpri c
2 (C) notice the sunflowers
--
TODO: 1 of 3 tasks shown
EOF
test_todo_session 'listpri highlighting' <<EOF
>>> todo.sh listpri
1 (B) smell the uppercase Roses +flowers @outside
2 (C) notice the sunflowers
--
TODO: 2 of 3 tasks shown
EOF
cat > todo.txt <<EOF
(B) smell the uppercase Roses +flowers @outside
(C) notice the sunflowers
(m)others will notice this
(n) not a prioritized task
notice the (C)opyright
EOF
test_todo_session 'listpri filtering priorities' <<EOF
>>> todo.sh -p listpri
1 (B) smell the uppercase Roses +flowers @outside
2 (C) notice the sunflowers
--
TODO: 2 of 5 tasks shown
>>> todo.sh -p listpri b
1 (B) smell the uppercase Roses +flowers @outside
--
TODO: 1 of 5 tasks shown
>>> todo.sh -p listpri c
2 (C) notice the sunflowers
--
TODO: 1 of 5 tasks shown
>>> todo.sh -p listpri m
--
TODO: 0 of 5 tasks shown
>>> todo.sh -p listpri n
--
TODO: 0 of 5 tasks shown
EOF
cat > todo.txt <<EOF
(B) ccc xxx this line should be third.
ccc xxx this line should be third.
(A) aaa zzz this line should be first.
aaa zzz this line should be first.
(B) bbb yyy this line should be second.
bbb yyy this line should be second.
EOF
test_todo_session 'listpri filtering of TERM' <<EOF
>>> todo.sh -p listpri "should be"
3 (A) aaa zzz this line should be first.
5 (B) bbb yyy this line should be second.
1 (B) ccc xxx this line should be third.
--
TODO: 3 of 6 tasks shown
>>> todo.sh -p listpri a "should be"
3 (A) aaa zzz this line should be first.
--
TODO: 1 of 6 tasks shown
>>> todo.sh -p listpri b second
5 (B) bbb yyy this line should be second.
--
TODO: 1 of 6 tasks shown
>>> todo.sh -p listpri x "should be"
--
TODO: 0 of 6 tasks shown
EOF
test_done

View File

@@ -1,42 +0,0 @@
#!/bin/sh
test_description='list project functionality
'
. ./test-lib.sh
cat > todo.txt <<EOF
(B) smell the uppercase Roses +roses @outside +shared
(C) notice the sunflowers +sunflowers @garden +shared +landscape
stop
EOF
test_todo_session 'basic listproj' <<EOF
>>> todo.sh listproj
+landscape
+roses
+shared
+sunflowers
EOF
test_todo_session 'listproj with context' <<EOF
>>> todo.sh listproj @garden
+landscape
+shared
+sunflowers
EOF
TEST_TODO_CUSTOM=todo-custom.cfg
cat todo.cfg > "$TEST_TODO_CUSTOM"
cat >> "$TEST_TODO_CUSTOM" <<'EOF'
export DEFAULT='</color>'
export PRI_B='<color type=green>'
export PRI_C='<color type=blue>'
export TODOTXT_FINAL_FILTER='grep -i roses'
EOF
test_todo_session 'listproj with context special cases' <<EOF
>>> todo.sh -+ -d "$TEST_TODO_CUSTOM" listproj @garden
+landscape
+shared
+sunflowers
EOF
test_done

View File

@@ -94,40 +94,6 @@ TODO: 1 of 3 tasks shown
TODO: 1 of 3 tasks shown
EOF
#
# check the filtering of TERM containing characters that are special to the
# shell, like variables, quotes, and multiple subsequent spaces.
#
cat > todo.txt <<'EOF'
earn some pennies
earn some $$
earn some "money"
get money from O'Brian
just get money!
EOF
test_todo_session 'checking filtering of special characters' <<'EOF'
>>> todo.sh ls '$$'
2 earn some $$
--
TODO: 1 of 5 tasks shown
>>> todo.sh ls '"money"'
3 earn some "money"
--
TODO: 1 of 5 tasks shown
>>> todo.sh ls "O'Brian"
4 get money from O'Brian
--
TODO: 1 of 5 tasks shown
>>> todo.sh ls "get money"
5 just get money!
--
TODO: 1 of 5 tasks shown
EOF
#
# check the x command line option
#

View File

@@ -57,34 +57,6 @@ test_todo_session 'prepend with &' <<EOF
3 no running & jumping now stop
EOF
echo 'jump on hay' > todo.txt
test_todo_session 'prepend with spaces' <<EOF
>>> todo.sh prepend 1 "notice the three spaces and"
1 notice the three spaces and jump on hay
EOF
cat > todo.txt <<EOF
smell the cows
grow some corn
thrash some hay
chase the chickens
EOF
test_todo_session 'prepend with symbols' <<EOF
>>> todo.sh prepend 1 "~@#$%^&*()-_=+[{]}|;:',<.>/?"
1 ~@#$%^&*()-_=+[{]}|;:',<.>/? smell the cows
>>> todo.sh prepend 2 '\`!\\"'
2 \`!\\" grow some corn
>>> todo.sh list
4 chase the chickens
3 thrash some hay
2 \`!\\" grow some corn
1 ~@#$%^&*()-_=+[{]}|;:',<.>/? smell the cows
--
TODO: 4 of 4 tasks shown
EOF
cat /dev/null > todo.txt
test_todo_session 'prepend handling prepended date on add' <<EOF
>>> todo.sh -t add "new task"

View File

@@ -17,12 +17,6 @@ test_todo_session 'append usage' <<EOF
usage: todo.sh append ITEM# "TEXT TO APPEND"
EOF
test_todo_session 'append error' << EOF
>>> todo.sh append 10 "hej!"
=== 1
TODO: No task 10.
EOF
test_todo_session 'basic append' <<EOF
>>> todo.sh append 1 "smell the roses"
1 notice the daisies smell the roses
@@ -43,32 +37,11 @@ test_todo_session 'basic append with &' <<EOF
TODO: 1 of 1 tasks shown
EOF
echo 'jump on hay' > todo.txt
test_todo_session 'append with spaces' <<EOF
>>> todo.sh append 1 "and notice the three spaces"
1 jump on hay and notice the three spaces
EOF
cat > todo.txt <<EOF
smell the cows
grow some corn
thrash some hay
chase the chickens
EOF
test_todo_session 'append with symbols' <<EOF
>>> todo.sh append 1 "~@#$%^&*()-_=+[{]}|;:',<.>/?"
1 smell the cows ~@#$%^&*()-_=+[{]}|;:',<.>/?
>>> todo.sh append 2 '\`!\\"'
2 grow some corn \`!\\"
>>> todo.sh list
4 chase the chickens
2 grow some corn \`!\\"
1 smell the cows ~@#$%^&*()-_=+[{]}|;:',<.>/?
3 thrash some hay
--
TODO: 4 of 4 tasks shown
test_todo_session 'append error' << EOF
>>> todo.sh append 10 "hej!"
=== 1
TODO: No task 10.
EOF
cat > todo.txt <<EOF

142
todo.sh
View File

@@ -1,7 +1,7 @@
#! /bin/bash
# === HEAVY LIFTING ===
shopt -s extglob extquote
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.
@@ -58,8 +58,8 @@ shorthelp()
listall|lsa [TERM...]
listcon|lsc
listfile|lf SRC [TERM...]
listpri|lsp [PRIORITY] [TERM...]
listproj|lsprj [TERM...]
listpri|lsp [PRIORITY]
listproj|lsprj
move|mv ITEM# DEST [SRC]
prepend|prep ITEM# "TEXT TO PREPEND"
pri|p ITEM# PRIORITY
@@ -143,11 +143,10 @@ help()
sorted by priority with line numbers. If TERM specified, lists
all lines that contain TERM in SRC file.
listpri [PRIORITY] [TERM...]
lsp [PRIORITY] [TERM...]
listpri [PRIORITY]
lsp [PRIORITY]
Displays all tasks prioritized PRIORITY.
If no PRIORITY specified, lists all prioritized tasks.
If TERM specified, lists only prioritized tasks that contain TERM.
listproj
lsprj
@@ -268,17 +267,16 @@ cleanup()
cleaninput()
{
# Replace CR and LF with space; tasks always comprise a single line.
input=${input//$'\r'/ }
input=${input//$'\n'/ }
# Cleanup the input
# Replace newlines with spaces Always
input=`echo $input | tr -d '\r\n'`
if [ "$1" = "for sed" ]; then
# This action uses sed with "|" as the substitution separator, and & as
# the matched string; these must be escaped.
# Backslashes must be escaped, too, and before the other stuff.
input=${input//\\/\\\\}
input=${input//|/\\|}
input=${input//&/\\&}
action_regexp="^\(append\|app\|prepend\|prep\|replace\)$"
# Check which action we are being used in as this affects what cleaning we do
if [ `echo $action | grep -c $action_regexp` -eq 1 ]; then
# These actions use sed and & as the matched string so escape it
input=`echo $input | sed 's/\&/\\\&/g'`
fi
}
@@ -323,7 +321,7 @@ replaceOrPrepend()
else
input=$*
fi
cleaninput "for sed"
cleaninput $input
# Retrieve existing priority and prepended date
priority=$(sed -e "$item!d" -e $item's/^\((.) \)\{0,1\}\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{0,1\}.*/\1/' "$TODO_FILE")
@@ -533,7 +531,7 @@ export SENTENCE_DELIMITERS=',.:;'
}
[ -e "$TODOTXT_CFG_FILE" ] || {
CFG_FILE_ALT=$(dirname "$0")"/todo.cfg"
CFG_FILE_ALT=`dirname "$0"`"/todo.cfg"
if [ -e "$CFG_FILE_ALT" ]
then
@@ -617,11 +615,11 @@ fi
_addto() {
file="$1"
input="$2"
cleaninput
cleaninput $input
if [[ $TODOTXT_DATE_ON_ADD = 1 ]]; then
now=$(date '+%Y-%m-%d')
input=$(echo "$input" | sed -e 's/^\(([A-Z]) \)\{0,1\}/\1'"$now /")
now=`date '+%Y-%m-%d'`
input="$now $input"
fi
echo "$input" >> "$file"
if [ $TODOTXT_VERBOSE -gt 0 ]; then
@@ -633,42 +631,6 @@ _addto() {
fi
}
shellquote()
{
typeset -r qq=\'; printf %s\\n "'${1//\'/${qq}\\${qq}${qq}}'";
}
filtercommand()
{
filter=${1:-}
shift
post_filter=${1:-}
shift
for search_term
do
## See if the first character of $search_term is a dash
if [ "${search_term:0:1}" != '-' ]
then
## First character isn't a dash: hide lines that don't match
## this $search_term
filter="${filter:-}${filter:+ | }grep -i $(shellquote "$search_term")"
else
## First character is a dash: hide lines that match this
## $search_term
#
## Remove the first character (-) before adding to our filter command
filter="${filter:-}${filter:+ | }grep -v -i '$(shellquote "${search_term:1}")'"
fi
done
[ -n "$post_filter" ] && {
filter="${filter:-}${filter:+ | }${post_filter:-}"
}
printf %s "$filter"
}
_list() {
local FILE="$1"
## If the file starts with a "/" use absolute path. Otherwise,
@@ -692,8 +654,32 @@ _list() {
## Get our search arguments, if any
shift ## was file name, new $1 is first search term
## Build the filter.
filter_command=$(filtercommand "${pre_filter_command:-}" "${post_filter_command:-}" "$@")
## Prefix the filter_command with the pre_filter_command
filter_command="${pre_filter_command:-}"
for search_term
do
## See if the first character of $search_term is a dash
if [ "${search_term:0:1}" != '-' ]
then
## First character isn't a dash: hide lines that don't match
## this $search_term
filter_command="${filter_command:-} ${filter_command:+|} \
grep -i \"$search_term\" "
else
## First character is a dash: hide lines that match this
## $search_term
#
## Remove the first character (-) before adding to our filter command
filter_command="${filter_command:-} ${filter_command:+|} \
grep -v -i \"${search_term:1}\" "
fi
done
## If post_filter_command is set, append it to the filter_command
[ -n "$post_filter_command" ] && {
filter_command="${filter_command:-}${filter_command:+ | }${post_filter_command:-}"
}
## Figure out how much padding we need to use
## We need one level of padding for each power of 10 $LINES uses
@@ -711,7 +697,7 @@ _list() {
| grep -v "^[ 0-9]\+ *$"
)
if [ "${filter_command}" ]; then
filtered_items=$(echo -n "$items" | eval "${filter_command}")
filtered_items=$(echo -n "$items" | eval ${filter_command})
else
filtered_items=$items
fi
@@ -764,7 +750,7 @@ _list() {
fi
}
export -f cleaninput shellquote filtercommand _list die
export -f _list die
# == HANDLE ACTION ==
action=$( printf "%s\n" "$ACTION" | tr 'A-Z' 'a-z' )
@@ -856,7 +842,7 @@ case $action in
[$SENTENCE_DELIMITERS]*) appendspace=;;
*) appendspace=" ";;
esac
cleaninput "for sed"
cleaninput $input
if sed -i.bak $item" s|^.*|&${appendspace}${input}|" "$TODO_FILE"; then
if [ $TODOTXT_VERBOSE -gt 0 ]; then
@@ -930,12 +916,12 @@ case $action in
# Split multiple depri's, if comma separated change to whitespace separated
# Loop the 'depri' function for each item
for item in $(echo $* | tr ',' ' '); do
for item in `echo $* | tr ',' ' '`; do
[[ "$item" = +([0-9]) ]] || die "$errmsg"
todo=$(sed "$item!d" "$TODO_FILE")
[ -z "$todo" ] && die "TODO: No task $item."
if [[ "$todo" = \(?\)\ * ]]; then
if sed "$item!d" "$TODO_FILE" | grep "^(.) " > /dev/null; then
sed -i.bak -e $item"s/^(.) //" "$TODO_FILE"
if [ $TODOTXT_VERBOSE -gt 0 ]; then
NEWTODO=$(sed "$item!d" "$TODO_FILE")
@@ -956,7 +942,7 @@ case $action in
# Split multiple do's, if comma separated change to whitespace separated
# Loop the 'do' function for each item
for item in $(echo $* | tr ',' ' '); do
for item in `echo $* | tr ',' ' '`; do
[ -z "$item" ] && die "$errmsg"
[[ "$item" = +([0-9]) ]] || die "$errmsg"
@@ -964,8 +950,8 @@ case $action in
[ -z "$todo" ] && die "TODO: No task $item."
# Check if this item has already been done
if [ "${todo:0:2}" != "x " ]; then
now=$(date '+%Y-%m-%d')
if [ `echo $todo | grep -c "^x "` -eq 0 ] ; then
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"
@@ -1019,16 +1005,26 @@ case $action in
;;
"listproj" | "lsprj" )
shift
eval "$(filtercommand 'cat "$TODO_FILE"' '' "$@")" | grep -o '[^ ]*+[^ ]\+' | grep '^+' | sort -u
grep -o '[^ ]*+[^ ]\+' "$TODO_FILE" | grep '^+' | sort -u
;;
"listpri" | "lsp" )
shift ## was "listpri", new $1 is priority to list or first TERM
shift ## was "listpri", new $1 is priority to list
pri=$(printf "%s\n" "$1" | tr 'a-z' 'A-Z' | grep '^[A-Z]$') && shift || pri="[A-Z]"
post_filter_command="grep '^ *[0-9]\+ (${pri}) '"
_list "$TODO_FILE" "$@"
if [ "${1:-}" ]
then
## A priority was specified
pri=$( printf "%s\n" "$1" | tr 'a-z' 'A-Z' | grep '^[A-Z]$' ) || {
die "usage: $TODO_SH listpri PRIORITY
note: PRIORITY must a single letter from A to Z."
}
else
## No priority specified; show all priority tasks
pri="[A-Z]"
fi
pri="($pri)"
_list "$TODO_FILE" "$pri"
;;
"move" | "mv" )