| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 | 
							- #!/bin/bash
 - 
 - OVERDUER_FILTER=${OVERDUER_FILTER:-"( +OVERDUE or +WEEK )"}
 - 
 - usage() {
 -     local self
 -     self=$(basename "$0")
 -     echo "usage: $self [--] [FILTER]" >&2
 -     echo "usage: $self --help" >&2
 -     exit 2
 - }
 - 
 - help() {
 -     local self
 -     self=$(basename "$0")
 -     echo "Usage:"
 -     echo "  $self [-H] [-i] [--] [FILTER...]"
 -     echo ""
 -     echo "TaskWarrior wrapper to help manage (approaching!) due dates."
 -     echo ""
 -     echo "Options:"
 -     echo ""
 -     echo "  --  Stop processing options; treat rest of arguments as"
 -     echo "      TaskWarrior filter expression."
 -     echo ""
 -     echo "  -n  Do not modify any tasks; just show command that would do so."
 -     echo "      Note: this does not turn off listing commands which, by design"
 -     echo "      of TaskWarrior, can change numeric task IDs (not UUIDs)."
 -     echo ""
 -     echo "  -H  Do not include help messages in the template."
 -     echo ""
 -     echo "  -i  Include details of each task (\`task info\`) inside the"
 -     echo "      template."
 -     echo ""
 -     echo "$self will use listing of TaskWarrior tasks past or close to their"
 -     echo "due date to create a template that will be automatically opened in"
 -     echo "your favorite editor.  By editing the template and exiting the"
 -     echo "editor, you can assign new due dates to any of these tasks."
 -     echo "(Read instructions embedded inside the template for details.)"
 -     echo ""
 -     echo "If any tasks are modified, their new state is printed after the"
 -     echo "fact.  (Hint: use \`task undo\` to revert last change)."
 -     echo ""
 -     echo "By default, filter '( +OVERDUE or +WEEK )' is used.  This can be"
 -     echo "overriden by setting environment variable OVERDUER_FILTER or"
 -     echo "specifying filter expression directly on command line."
 -     echo ""
 -     echo "You need to have vipe (from moreutils) installed and set EDITOR"
 -     echo "environment variable, see vipe(1) for details."
 -     exit 0
 - }
 - 
 - warn() {
 -     local msg
 -     for msg in "$@";
 -     do
 -         echo "$msg" >& 2
 -     done
 - }
 - 
 - distill() {
 -     #
 -     # Remove comments and everything except due expression and UUID from stdin
 -     #
 -     local due
 -     local rest
 -     local uuid
 -     grep -v "^[[:space:]]*#" \
 -       | while read -r due rest;
 -         do
 -             test -n "$due" || continue
 -             uuid=${rest##* }
 -             test -n "$uuid" || continue
 -             echo "$due $uuid"
 -         done
 - }
 - 
 - maybe_do() {
 -     #
 -     # Maybe do it, maybe just say it
 -     #
 -     case $Dry in
 -         true)   warn "$*" ;;
 -         false)  "$@" ;;
 -     esac
 - }
 - 
 - apply() {
 -     #
 -     # Apply each pair of DUE UUID on stdin
 -     #
 -     local due
 -     local uuid
 -     local es=0
 -     while read -r due uuid;
 -     do
 -         task info "$uuid" >/dev/null || {
 -             warn "ignoring invalid UUID: $due for $uuid"
 -             es=3
 -             continue
 -         }
 -         task calc "$due" >/dev/null || {
 -             warn "ignoring invalid due date: $due for $uuid"
 -             es=3
 -             continue
 -         }
 -         maybe_do task "$uuid" modify "due:$due"
 -         task "$uuid" info
 -     done
 -     return $es
 - }
 - 
 - mkhelp1() {
 -     #
 -     # Print first part (before listing) of the help text
 -     #
 -     $AddHelp || return 0
 -     echo "#"
 -     echo "# Edit due dates below to your liking.  The resulting format"
 -     echo "# must be:"
 -     echo "#"
 -     echo "#     TIME [anything] UUID"
 -     echo "#"
 -     echo "# where TIME is a valid TaskWarrior time expression (hint: use"
 -     echo "# \`task calc TIME\`) and UUID, well, a valid task UUID.  The"
 -     echo "# [anything] part is provided only for your convenience and will"
 -     echo "# be ignored."
 -     echo "#"
 -     echo "# What will also be ignored:"
 -     echo "#"
 -     echo "#  *  comments like this,"
 -     echo "#  *  empty lines,"
 -     echo "#  *  template lines that were left unchanged."
 -     echo "#"
 -     echo
 -     echo "#"
 -     echo "# CUR_DUE ID DESCRIPTION                                                            UUID"
 -     echo
 - }
 - 
 - mkhelp2() {
 -     #
 -     # Print second part (after the listing) of the help text
 -     #
 -     $AddHelp || return 0
 -     echo
 -     echo "#"
 -     echo "# Note that CUR_DUE is ONLY DATE, NOT TIME, while actual due"
 -     echo "# time may be set more precisely.  If that matters, consult"
 -     echo "# full task info using syntax such as \`task ID info\` or -i."
 -     echo "# switch."
 -     echo "#"
 - }
 - 
 - mklisting() {
 -     #
 -     # Print task listing in form of "CUR_DUE If DESCRIPTION UUID"
 -     #
 -     task rc.detection:off rc.verbose:nothing \
 -         rc.defaultwidth:120 \
 -         rc.report.OVERDUER.columns:due,id,description,uuid \
 -         rc.report.OVERDUER.labels:DUE,ID,DESC,UUID \
 -         "${TaskFilter[@]}" \
 -         OVERDUER 2>/dev/null \
 -       | grep '^[^ ]' \
 -       | grep -v "^[[:space:]]*-" \
 -       | grep -v "^[[:space:]]*[A-Z]" \
 -       | sort
 - }
 - 
 - mkinfos() {
 -     #
 -     # Print extra info for each listed task; all commented out
 -     #
 -     local uuid
 -     $AddInfos || return 0
 -     echo ""
 -     echo ""
 -     echo "#              #"
 -     echo "# Task details #"
 -     echo "#              #"
 -     echo ""
 -     mklisting \
 -       | rev | cut -d' ' -f1 | rev \
 -       | while read -r uuid;
 -         do
 -             task "$uuid" info 2>/dev/null \
 -               | sed "s/^/# /"
 -             echo
 -         done
 - }
 - 
 - mktemplate() {
 -     #
 -     # Construct template text
 -     #
 -     mkhelp1
 -     mklisting
 -     mkhelp2
 -     mkinfos
 - }
 - 
 - main() {
 -     local Dry=false
 -     local tmp
 -     local es=0
 -     local AddHelp=true
 -     local AddInfos=false
 -     local TaskFilter=()
 -     while true; do case $1 in
 -         -n)     Dry=true;      shift ;;
 -         -H)     AddHelp=false; shift ;;
 -         -i)     AddInfos=true; shift ;;
 -         --)     shift; break ;;
 -         --help) help  ;;
 -         -*)     usage ;;
 -         *)      break ;;
 -     esac done
 -     which vipe >/dev/null || {
 -         warn "fatal: vipe is not installed"
 -         exit 3
 -     }
 -     TaskFilter=("$@")
 -     test -n "${TaskFilter[*]}" || TaskFilter=("$OVERDUER_FILTER")
 -     tmp=$(mktemp -d -t overduer.main.XXXXXXXX)
 -     mktemplate \
 -       | tee "$tmp/old" \
 -       | vipe > "$tmp/new"
 -     <"$tmp/old" distill | sort >"$tmp/old.distilled"
 -     <"$tmp/new" distill | sort >"$tmp/new.distilled"
 -     comm -13 "$tmp/old.distilled" "$tmp/new.distilled" > "$tmp/changes"
 -     if test -s "$tmp/changes";
 -     then
 -         <"$tmp/changes" apply; es=$?
 -     else
 -         warn "no changes detected; nothing to do"
 -         es=1
 -     fi
 -     rm -r "$tmp"
 -     return $es
 - }
 - 
 - main "$@"
 
 
  |