7 t [-aDT] [-s REGEX_STRING] [-d [INTEGER|REGEX_STRING]]
10 t print incomplete todos
12 t -D print all done todos
13 t -s call print all todos matching "call"
14 t -s "call|email" print all todos matching "call" or "email"
15 t -D -s read print all done todos matching "read"
16 t -d 12 mark todo item 12 as done
17 t -s read -d 3 mark todo item 3 within todos matching "read" as done
18 t -d burn mark all todos matching "burn" as done
19 t -s burn -d . same as above
20 t -k 7 delete todo item 7
21 t -k bunnies delete all todos matching "bunnies"
22 t -s bunnies -k . same as above
23 t -e edit TODO_FILE in $EDITOR
24 t -T sell horse add todo "sell horse" due today
25 t -n print unnumbered output (suitable for redirection)
30 re_todo_file='[Tt][Oo][Dd][Oo].*'
33 re_either='^- \[[ xX]] '
34 re_date='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
37 expr "$f" : "$re_todo_file" > /dev/null && todo_file="$f" && break
40 if [ ! "$todo_file" ]; then
41 if [ -r "$TODO_FILE" ]; then
42 todo_file="$TODO_FILE"
44 echo 'No todo file found'
50 # returns: sorted list of matching todos
54 expr "$query" : '\(.*[A-Z].*\)' > /dev/null && casematch='-i'
55 todo_list=$(grep $casematch "$re_prefix.*$*" "$todo_file")
57 if [ -n "$todo_list" ]; then
58 due_list=$(echo "$todo_list" | grep "$re_date")
59 todo_list=$(echo "$todo_list" | grep -v "$re_date")
60 due_list=$(echo "$due_list" | sed -E "s/.*($re_date).*/\1&/" |
61 sort -n | sed -E "s/^$re_date//")
63 # printf '%s\n%s\n' "$due_list" "$todo_list"
64 if [ -n "$due_list" ] && [ -n "$todo_list" ]; then
65 printf '%s\n%s\n' "$due_list" "$todo_list"
66 elif [ -n "$due_list" ]; then
67 printf '%s\n' "$due_list"
69 printf '%s\n' "$todo_list"
75 # returns: todo list printed to stdout
78 if [ -n "$input" ]; then
80 n_width=$(echo "$input" | wc -l | xargs | wc -c)
82 echo "$input" | while read -r todo; do
83 date=$(expr "$todo" : ".*\($re_date\)" | sed 's/-//g')
86 if [ -n "$date" ] && [ -z "$onlydone$showall" ]; then
88 if [ "$date" -gt "$today" ]; then
90 sed -E "s/($re_prefix)(.*)/\1** \2 **/")
94 if [ -n "$export" ]; then
95 printf "%s\n" "${todo}"
97 printf "%${n_width}s %s\n" "$n" "${todo#- }"
104 # t_select(number|regex)
105 # returns: selected todos
107 if expr "$1" + 0 > /dev/null 2>&1; then
111 expr "$1" : '.*[A-Z].*' > /dev/null && casematch='-i'
116 # t_done(number|regex)
117 # returns: altered todo_file
120 while read -r todo; do
123 '$0 == str { gsub (/- \[ ]/, "- [x]") } { print }' \
124 "$todo_file" > "$tmp"
125 mv "$tmp" "$todo_file"
132 while read -r todo; do
134 awk -v str="$todo" '$0 != str' "$todo_file" > "$tmp"
135 mv "$tmp" "$todo_file"
141 while read -r todo; do
144 expr "$todo" : "$re_done" > /dev/null &&
145 check='- [ ]' || check='- [x]'
146 awk -v str="$todo" -v check="$check" \
147 '$0 == str { gsub (/- \[[ xX]]/, check) } { print }' \
148 "$todo_file" > "$tmp"
149 mv "$tmp" "$todo_file"
154 t_select "$1" | grep -Eo "https?://[^ ]+" | xargs open
157 while getopts ':ab:Dd:ehk:ns:Tz:' opt; do
161 (b) openurl=$OPTARG;;
163 (d) markdone=$OPTARG;;
164 (e) ${EDITOR:-vi} "$todo_file"; exit 0;;
168 (T) due=" $(date +%F)";;
170 (:) printf "t: option -%s requires an argument\n" "$OPTARG"
172 (*) printf "t: unrecognized option -%s\n\n" "$OPTARG"
177 shift "$(( OPTIND - 1 ))"
179 if [ -n "$onlydone" ]; then
181 elif [ -n "$showall" ]; then
182 re_prefix="$re_either"
187 if [ -n "$markdone" ]; then t_read "$query" | t_done "$markdone"
188 elif [ -n "$toggle" ]; then t_read "$query" | t_toggle "$toggle"
189 elif [ -n "$kill" ]; then t_read "$query" | t_kill "$kill"
190 elif [ -n "$openurl" ]; then t_read "$query" | t_openurl "$openurl"
191 elif [ -n "$query" ]; then t_read "$query" | t_print "$re_prefix"
192 elif [ -n "$*" ]; then
193 echo "- [ ] $*${due}" >> "$todo_file"
194 else t_read | t_print "$re_prefix"