#compdef todo.sh _todo() { local curcontext="$curcontext" state state_descr line typeset -A opt_args local -a args commands subcmds local _todo_sh=${_todo_sh:-${words[1]}} local -r MOVE_COMMAND_PATTERN='(move|mv)' local -r OPTS=('-@' '-@@' '-+' '-++' '-d' '-f' '-h' '-p' '-P' '-PP' '-a' '-n' '-t' '-v' '-vv' '-V' '-x') local -r COMMANDS=( 'add:a new task' 'a:add alias' 'addto:add to file' 'addm:add multiple' 'append:app:app:append to task' 'archive:move done tasks to archive' 'command:run addon' 'del:rm:delete task' 'depri:dp:remove priority' 'do:mark as done' 'help:show help' 'list:ls:list tasks' 'listaddons:show installed addons' 'listall:lsa:list all tasks' 'listcon:lsc:list contexts' 'listfile:lf:list files' 'listpri:lsp:list by priority' 'listproj:lsprj:list projects' 'move:mv:move task between files' 'prepend:insert text at beginning' 'pri:p:set priority' 'replace:modify task' 'report:generate report' 'shorthelp:brief help' ) _arguments -C \ "1: :->cmds" \ "*:: :->args" case $state in cmds) local addons=($(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listaddons 2>/dev/null)) args=($COMMANDS $addons $OPTS) _describe 'todo.sh command' args ;; args) cur="${words[CURRENT]}" prev="${words[CURRENT-1]}" case "$prev" in command) _describe 'subcommand' COMMANDS ;; help) local addons=($(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listaddons 2>/dev/null)) args=($COMMANDS $addons) _describe 'help topic' args ;; addto|listfile|lf|move|mv) local files=($(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listfile 2>/dev/null)) _describe 'file' files ;; *) case "$cur" in due:*) _values 'due date' $(seq 0 30 | xargs -I{} date -d "+{} days" +%Y-%m-%d) ;; *@today*|*@now*) _wanted dates expl 'date' compadd -S '' -- $(date +%Y-%m-%d) ;; +*) local projects=($(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listproj 2>/dev/null)) [[ ${#projects} -eq 0 ]] && projects=($(eval TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE "$_todo_sh" command listproj 2>/dev/null)) _describe 'project' projects -p '+' ;; @*) local contexts=($(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listcon 2>/dev/null)) [[ ${#contexts} -eq 0 ]] && contexts=($(eval TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE "$_todo_sh" command listcon 2>/dev/null)) _describe 'context' contexts -p '@' ;; [0-9]##) local task=($(eval TODOTXT_VERBOSE=0 "$_todo_sh" \ '-@ -+ -p -x command ls "^ *${cur} "' 2>/dev/null | \ sed -e 's/^ *[0-9]\{1,\} //' \ -e 's/^\((.) \)\{0,1\}[0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} /\1/' \ -e 's/^\([xX] \)\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{1,2\}/\1/' \ -e 's/[[:space:]]*$//' -e '1q')) _message -r "Task ${cur}: ${task}" ;; *) if [[ ${words[1]} == $~MOVE_COMMAND_PATTERN ]] && (( CURRENT == 3 )); then local files=($(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listfile 2>/dev/null)) _describe 'destination file' files else _files fi ;; esac ;; esac ;; esac } _todo "$@"