title | desc | tags | ||||
---|---|---|---|---|---|---|
My Todo Manager |
Making a Suckless Todo manager which also syncs with calcurse |
|
In my previous post about my Calender Setup, I mentioned about how I was using Calcurse as my calender. Now calcurse also has a Todo section which works great, except that I have to open calcurse to use it. I just want to quickly see what I need to do, press enter to say I am done with it and it should be gone. Adding an entry should be just as easy
dmenu
is a suckless menu selector which has fuzzy search (patch), default text (patch) and autocomplete. This is everything I need. So I made a script to use dmenu as my So I simply read the calcurse todo file and display a menu with each entry in the todo as a dmenu entry.
When user inputs, I check if it matches any previous entry. If it does, then I remove the entry from the todo file.
When the user input does not match any entry, it is assumed to be a new entry, and added to the file.
This solution has 2 problems,
- Calcurse uses a numbered ranking to signify the urgency of the entry. But adding a new entry at the default urgency is hard to type:
[0] Something I have to do
. So if the new entry input doesn't start with\[.\]
, the script just adds[0]
- There is no way to edit an entry. So I changed the script to put back the last deleted entry into the prompt. So an
edit
is actually a delete followed by a re-entry. If you really wanted to delete an entry, then just hitctrl-u
to clear the line.
I added a keybind to dwm to run my script, and everything works so beautifully. Now I can go and remove the todo entry to write this post.
Here is the final script-
#!/bin/zsh
#
# Write/remove a task to do later.
#
# Select an existing entry to remove it from the file, or type a new entry to
# add it.
#
file="$HOME/.calcurse/todo"
touch "$file"
height=$(wc -l "$file" | awk '{print $1}')
prompt="Add/delete a task: "
cmd=$(sort -r "$file" | dmenu -l "$height" -p "$prompt" -i )
while [ -n "$cmd" ]; do
if grep -qF "$cmd" "$file"; then
grep -vF "$cmd" "$file" > "$file.new" # This selects all the lines that DONT match
mv "$file.new" "$file"
(( height = height - 1 ))
else
if [[ "$(echo $cmd | tr -d \\n)" =~ "^\[[[:digit:]]\]" ]]; then
echo "$cmd" >> "$file"
else
echo "[0] $cmd" >> "$file"
fi
cmd=""
(( height = height + 1 ))
fi
cmd=$(sort -r "$file" | dmenu -l "$height" -p "$prompt" -it "$cmd" "$@" )
done
exit 0