Implemented `todo -L`, listing the hashes of all entries, or those on the given tags
[todo.git] / todo.sh
blob5cc0fbd4573f5822a1c07b7252fac88a078d2b0d
1 #!/bin/sh
2 # TODO, a cli GTD toy
3 # Copyright (C) 2008 Alejandro Mery <amery@geeks.cl>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 todo_usage()
20 local cmd="${0##*/}"
22 [ $# -eq 0 ] || echo "ERROR: $*" >&2
23 cat <<-EOT >&2
24 Usage: $0 [options] [<object>]
25 ${cmd} [-t <tag>*] [<message>] - new entry
26 ${cmd} [-T|--tags] - list tags
27 ${cmd} [-L] [<tag>*] - list entry hashes
29 EOT
30 exit 1
33 todo_trap()
35 echo "Ctrl-C pressed, aborting." >&2
36 rm -rf "$TODOTMP"
37 exit 1
40 todo_sane_tags()
42 echo "$*" | tr 'a-z' 'A-Z' | sed \
43 -e 's/^ *//' -e 's/ *$//' -e 's/ */ /g'
46 trap ':' INT
48 options=$( getopt -o "t:TL" -l "tags" -- "$@" )
49 if [ $? -ne 0 ]; then
50 todo_usage
53 # load new arguments list
54 eval set -- "$options"
56 TAGS=
57 MODE=new
59 while [ $# -gt 0 ]; do
60 case "$1" in
61 -T|--tags)
62 MODE=tags ;;
63 -L)
64 MODE=list_raw ;;
66 -t) TAGS="$TAGS $2"; shift ;;
68 --) shift; break ;;
69 -*) todo_usage unknown option "$1"
71 esac
72 shift
73 done
75 TODODIR="$HOME/.todo"
77 todo_new()
79 TODOTMP="${TMP:-/tmp}/.todo.$$"
80 DATE=
81 # find a unique date/hash
83 while [ -z "$DATE" ]; do
84 DATE=$(date --rfc-3339=seconds)
85 DATEHASH=$( echo "$DATE" | sha1sum | cut -d' ' -f1 )
86 DATEHASH_1=$( echo "$DATEHASH" | cut -c 1 )
87 ENTRYDIR="$TODODIR/entries/$DATEHASH_1"
88 ENTRY="$ENTRYDIR/$DATEHASH"
90 if [ -e "$ENTRY" ]; then
91 DATE=
92 sleep 1
93 else
94 mkdir -p "$ENTRYDIR"
96 done
98 if [ $# -gt 0 ]; then
99 echo "$*" > "$TODOTMP"
100 echo "Added: $DATE" >> "$TODOTMP"
101 else
102 echo "Subject: ..." > "$TODOTMP.empty"
103 echo "Added: $DATE" >> "$TODOTMP.empty"
104 cp "$TODOTMP.empty" "$TODOTMP"
106 ${EDITOR:-vi} "$TODOTMP"
108 if cmp -s "$TODOTMP" "$TODOTMP.empty"; then
109 rm -f "$TODOTMP" "$TODOTMP.empty"
110 return
114 mv "$TODOTMP" "$ENTRY"
116 for tag in $(todo_sane_tags $TAGS) INBOX; do
117 [ -d "$TODODIR/$tag" ] || mkdir "$TODODIR/$tag"
119 ln -s "../entries/$DATEHASH_1/$DATEHASH" "$TODODIR/$tag/$DATEHASH"
120 done
122 echo "$DATEHASH"
125 todo_tags()
127 ls -1d "$TODODIR"/* | sed -e "s,^$TODODIR/,," | grep -v '^entries$'
130 todo_list_raw()
132 local tags="$(todo_sane_tags $TAGS $*)"
133 local tag=
134 if [ -n "$tags" ]; then
135 for tag in $tags; do
136 ls -1 "$TODODIR/$tag"/*
137 done
138 else
139 ls -1 "$TODODIR/entries"/*/*
140 fi 2> /dev/null | sed -e 's,.*/,,' | sort -u
142 case "$MODE" in
143 new) todo_new "$*" ;;
144 tags) todo_tags ;;
146 list_raw) todo_list_raw "$*" ;;
147 esac