Compare commits

...

4 Commits
list ... cygwin

Author SHA1 Message Date
Ingo Karkat
16b1cb5f98 ENH: Allow listpri filtering with priority ranges.
So far, the listpri action only supports a single priority. Allowing priority ranges (e.g. todo.sh listpri A-C @work) is a simple but useful enhancement.

Note: The syntax extension only clashes with the [TERM] filtering in a few corner cases, and this can be worked around (e.g. "todo.sh listpri A-Z A-Z" lists all prioritized tasks containing the text A-Z).
2012-02-14 21:00:32 -08:00
Ingo Karkat
78dab71a78 Also get rid of TMP_FILE in todo.cfg.
There's a slight chance that some add-on has used this (undocumented, unofficial) configuration value for its own purposes (and maybe also relied on the unexposed cleanup() infrastructure), but detecting and fixing that problem (by moving the cleanup into the add-on itself) is pretty straightforward.
2012-02-14 20:59:19 -08:00
Ingo Karkat
2a0bd60d5f Break up _list(), get rid of TMP_FILE.
Extract a new function _format() (and getPadding(), both also exported for add-ons) from _list(), which includes the main formatting and filtering pipeline, without the file handling and verbose summary. This can receive the todo file via stdin, so the listall action is able to format the concatenated files without going through a temporary file.

Eventually, after further refactorings, _format() could be used for actual formatted verbose messages in all commands; currently, the raw, unformatted task is printed.
2012-02-14 20:59:19 -08:00
Ingo Karkat
c8da8a640a Get rid of cleanup, only use TMP_FILE in listall.
After the recent refactorings, the temporary file is only needed for the listall action. Therefore, the creation-checks and eventual cleanup can be restricted to the listall action, which should slightly speed up the overall script execution.
2012-02-14 20:59:19 -08:00
3 changed files with 84 additions and 36 deletions

View File

@@ -61,6 +61,42 @@ TODO: 0 of 5 tasks shown
TODO: 0 of 5 tasks shown TODO: 0 of 5 tasks shown
EOF EOF
cat > todo.txt <<EOF
(B) smell the uppercase Roses +flowers @outside
(X) clean the house from A-Z
(C) notice the sunflowers
(X) listen to music
buy more records from artists A-Z
EOF
test_todo_session 'listpri filtering priority ranges' <<EOF
>>> todo.sh -p listpri a-c
1 (B) smell the uppercase Roses +flowers @outside
3 (C) notice the sunflowers
--
TODO: 2 of 5 tasks shown
>>> todo.sh -p listpri c-Z
3 (C) notice the sunflowers
2 (X) clean the house from A-Z
4 (X) listen to music
--
TODO: 3 of 5 tasks shown
>>> todo.sh -p listpri A-
2 (X) clean the house from A-Z
--
TODO: 1 of 5 tasks shown
>>> todo.sh -p listpri A-C A-Z
--
TODO: 0 of 5 tasks shown
>>> todo.sh -p listpri X A-Z
2 (X) clean the house from A-Z
--
TODO: 1 of 5 tasks shown
EOF
cat > todo.txt <<EOF cat > todo.txt <<EOF
(B) ccc xxx this line should be third. (B) ccc xxx this line should be third.
ccc xxx this line should be third. ccc xxx this line should be third.

View File

@@ -8,7 +8,6 @@ export TODO_DIR=`dirname "$0"`
export TODO_FILE="$TODO_DIR/todo.txt" export TODO_FILE="$TODO_DIR/todo.txt"
export DONE_FILE="$TODO_DIR/done.txt" export DONE_FILE="$TODO_DIR/done.txt"
export REPORT_FILE="$TODO_DIR/report.txt" export REPORT_FILE="$TODO_DIR/report.txt"
export TMP_FILE="$TODO_DIR/todo.tmp"
# You can customize your actions directory location # You can customize your actions directory location
#export TODO_ACTIONS_DIR="$HOME/.todo.actions.d" #export TODO_ACTIONS_DIR="$HOME/.todo.actions.d"

83
todo.sh
View File

@@ -59,7 +59,7 @@ shorthelp()
listall|lsa [TERM...] listall|lsa [TERM...]
listcon|lsc listcon|lsc
listfile|lf [SRC [TERM...]] listfile|lf [SRC [TERM...]]
listpri|lsp [PRIORITY] [TERM...] listpri|lsp [PRIORITIES] [TERM...]
listproj|lsprj [TERM...] listproj|lsprj [TERM...]
move|mv ITEM# DEST [SRC] move|mv ITEM# DEST [SRC]
prepend|prep ITEM# "TEXT TO PREPEND" prepend|prep ITEM# "TEXT TO PREPEND"
@@ -231,10 +231,11 @@ help()
Without any arguments, the names of all text files in the todo.txt Without any arguments, the names of all text files in the todo.txt
directory are listed. directory are listed.
listpri [PRIORITY] [TERM...] listpri [PRIORITIES] [TERM...]
lsp [PRIORITY] [TERM...] lsp [PRIORITIES] [TERM...]
Displays all tasks prioritized PRIORITY. Displays all tasks prioritized PRIORITIES.
If no PRIORITY specified, lists all prioritized tasks. PRIORITIES can be a single one (A) or a range (A-C).
If no PRIORITIES specified, lists all prioritized tasks.
If TERM specified, lists only prioritized tasks that contain TERM(s). If TERM specified, lists only prioritized tasks that contain TERM(s).
Hides all tasks that contain TERM(s) preceded by a minus sign Hides all tasks that contain TERM(s) preceded by a minus sign
(i.e. -TERM). (i.e. -TERM).
@@ -302,12 +303,6 @@ die()
exit 1 exit 1
} }
cleanup()
{
[ -f "$TMP_FILE" ] && rm "$TMP_FILE"
return 0
}
cleaninput() cleaninput()
{ {
# Parameters: When $1 = "for sed", performs additional escaping for use # Parameters: When $1 = "for sed", performs additional escaping for use
@@ -670,7 +665,6 @@ ACTION=${1:-$TODOTXT_DEFAULT_ACTION}
[ -d "$TODO_DIR" ] || die "Fatal Error: $TODO_DIR is not a directory" [ -d "$TODO_DIR" ] || die "Fatal Error: $TODO_DIR is not a directory"
( cd "$TODO_DIR" ) || die "Fatal Error: Unable to cd to $TODO_DIR" ( cd "$TODO_DIR" ) || die "Fatal Error: Unable to cd to $TODO_DIR"
[ -w "$TMP_FILE" ] || echo -n > "$TMP_FILE" || die "Fatal Error: Unable to write to $TMP_FILE"
[ -f "$TODO_FILE" ] || cp /dev/null "$TODO_FILE" [ -f "$TODO_FILE" ] || cp /dev/null "$TODO_FILE"
[ -f "$DONE_FILE" ] || cp /dev/null "$DONE_FILE" [ -f "$DONE_FILE" ] || cp /dev/null "$DONE_FILE"
[ -f "$REPORT_FILE" ] || cp /dev/null "$REPORT_FILE" [ -f "$REPORT_FILE" ] || cp /dev/null "$REPORT_FILE"
@@ -760,13 +754,32 @@ _list() {
## Get our search arguments, if any ## Get our search arguments, if any
shift ## was file name, new $1 is first search term shift ## was file name, new $1 is first search term
## Build the filter. _format "$src" '' "$@"
filter_command=$(filtercommand "${pre_filter_command:-}" "${post_filter_command:-}" "$@")
## Figure out how much padding we need to use if [ $TODOTXT_VERBOSE -gt 0 ]; then
## We need one level of padding for each power of 10 $LINES uses echo "--"
LINES=$( sed -n '$ =' "$src" ) echo "$(getPrefix "$src"): ${NUMTASKS:-0} of ${TOTALTASKS:-0} tasks shown"
PADDING=${#LINES} fi
}
getPadding()
{
## We need one level of padding for each power of 10 $LINES uses.
LINES=$(sed -n '$ =' "${1:-$TODO_FILE}")
printf %s ${#LINES}
}
_format()
{
# Parameters: $1: todo input file; when empty formats stdin
# $2: ITEM# number width; if empty auto-detects from $1 / $TODO_FILE.
# Precondition: None
# Postcondition: $NUMTASKS and $TOTALTASKS contain statistics (unless $TODOTXT_VERBOSE=0).
FILE=$1
shift
## Figure out how much padding we need to use, unless this was passed to us.
PADDING=${1:-$(getPadding "$FILE")}
shift
## Number the file, then run the filter command, ## Number the file, then run the filter command,
## then sort and mangle output some more ## then sort and mangle output some more
@@ -774,7 +787,11 @@ _list() {
TODOTXT_FINAL_FILTER="cat" TODOTXT_FINAL_FILTER="cat"
fi fi
items=$( items=$(
sed = "$src" \ if [ "$FILE" ]; then
sed = "$FILE"
else
sed =
fi \
| sed -e ''' | sed -e '''
N N
s/^/ / s/^/ /
@@ -782,6 +799,9 @@ _list() {
/^[ 0-9]\{1,\} *$/d /^[ 0-9]\{1,\} *$/d
''' '''
) )
## Build and apply the filter.
filter_command=$(filtercommand "${pre_filter_command:-}" "${post_filter_command:-}" "$@")
if [ "${filter_command}" ]; then if [ "${filter_command}" ]; then
filtered_items=$(echo -n "$items" | eval "${filter_command}") filtered_items=$(echo -n "$items" | eval "${filter_command}")
else else
@@ -827,16 +847,13 @@ _list() {
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ $TODOTXT_VERBOSE -gt 0 ]; then
NUMTASKS=$( echo -n "$filtered_items" | sed -n '$ =' ) NUMTASKS=$( echo -n "$filtered_items" | sed -n '$ =' )
TOTALTASKS=$( echo -n "$items" | sed -n '$ =' ) TOTALTASKS=$( echo -n "$items" | sed -n '$ =' )
echo "--"
echo "$(getPrefix "$FILE"): ${NUMTASKS:-0} of ${TOTALTASKS:-0} tasks shown"
fi fi
if [ $TODOTXT_VERBOSE -gt 1 ]; then if [ $TODOTXT_VERBOSE -gt 1 ]; then
echo "TODO DEBUG: Filter Command was: ${filter_command:-cat}" echo "TODO DEBUG: Filter Command was: ${filter_command:-cat}"
fi fi
} }
export -f cleaninput getPrefix getTodo getNewtodo shellquote filtercommand _list die export -f cleaninput getPrefix getTodo getNewtodo shellquote filtercommand _list getPadding _format die
# == HANDLE ACTION == # == HANDLE ACTION ==
action=$( printf "%s\n" "$ACTION" | tr 'A-Z' 'a-z' ) action=$( printf "%s\n" "$ACTION" | tr 'A-Z' 'a-z' )
@@ -854,9 +871,7 @@ then
elif [ -d "$TODO_ACTIONS_DIR" -a -x "$TODO_ACTIONS_DIR/$action" ] elif [ -d "$TODO_ACTIONS_DIR" -a -x "$TODO_ACTIONS_DIR/$action" ]
then then
"$TODO_ACTIONS_DIR/$action" "$@" "$TODO_ACTIONS_DIR/$action" "$@"
status=$? exit $?
cleanup
exit $status
fi fi
## Only run if $action isn't found in .todo.actions.d ## Only run if $action isn't found in .todo.actions.d
@@ -1082,16 +1097,16 @@ case $action in
"listall" | "lsa" ) "listall" | "lsa" )
shift ## Was lsa; new $1 is first search term shift ## Was lsa; new $1 is first search term
cat "$TODO_FILE" "$DONE_FILE" > "$TMP_FILE"
TOTAL=$( sed -n '$ =' "$TODO_FILE" ) TOTAL=$( sed -n '$ =' "$TODO_FILE" )
PADDING=${#TOTAL}
post_filter_command="awk -v TOTAL=$TOTAL -v PADDING=${#TOTAL} '{ \$1 = sprintf(\"%\" PADDING \"d\", (\$1 > TOTAL ? 0 : \$1)); print }' " post_filter_command="awk -v TOTAL=$TOTAL -v PADDING=$PADDING '{ \$1 = sprintf(\"%\" PADDING \"d\", (\$1 > TOTAL ? 0 : \$1)); print }' "
TODOTXT_VERBOSE=0 _list "$TMP_FILE" "$@" cat "$TODO_FILE" "$DONE_FILE" | TODOTXT_VERBOSE=0 _format '' "$PADDING" "$@"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ $TODOTXT_VERBOSE -gt 0 ]; then
TDONE=$( sed -n '$ =' "$DONE_FILE" ) TDONE=$( sed -n '$ =' "$DONE_FILE" )
TASKNUM=$(TODOTXT_PLAIN=1 TODOTXT_VERBOSE=0 _list "$TODO_FILE" "$@" | sed -n '$ =') TASKNUM=$(TODOTXT_PLAIN=1 TODOTXT_VERBOSE=0 _format "$TODO_FILE" 1 "$@" | sed -n '$ =')
DONENUM=$(TODOTXT_PLAIN=1 TODOTXT_VERBOSE=0 _list "$DONE_FILE" "$@" | sed -n '$ =') DONENUM=$(TODOTXT_PLAIN=1 TODOTXT_VERBOSE=0 _format "$DONE_FILE" 1 "$@" | sed -n '$ =')
echo "--" echo "--"
echo "$(getPrefix "$TODO_FILE"): ${TASKNUM:-0} of ${TOTAL:-0} tasks shown" echo "$(getPrefix "$TODO_FILE"): ${TASKNUM:-0} of ${TOTAL:-0} tasks shown"
echo "$(getPrefix "$DONE_FILE"): ${DONENUM:-0} of ${TDONE:-0} tasks shown" echo "$(getPrefix "$DONE_FILE"): ${DONENUM:-0} of ${TDONE:-0} tasks shown"
@@ -1124,8 +1139,8 @@ case $action in
"listpri" | "lsp" ) "listpri" | "lsp" )
shift ## was "listpri", new $1 is priority to list or first TERM shift ## was "listpri", new $1 is priority to list or first TERM
pri=$(printf "%s\n" "$1" | tr 'a-z' 'A-Z' | grep '^[A-Z]$') && shift || pri="[A-Z]" pri=$(printf "%s\n" "$1" | tr 'a-z' 'A-Z' | grep -e '^[A-Z]$' -e '^[A-Z]-[A-Z]$') && shift || pri="A-Z"
post_filter_command="grep '^ *[0-9]\+ (${pri}) '" post_filter_command="grep '^ *[0-9]\+ ([${pri}]) '"
_list "$TODO_FILE" "$@" _list "$TODO_FILE" "$@"
;; ;;
@@ -1283,5 +1298,3 @@ note: PRIORITY must be anywhere from A to Z."
* ) * )
usage;; usage;;
esac esac
cleanup