332 lines
9.2 KiB
Plaintext
332 lines
9.2 KiB
Plaintext
#compdef todo
|
|
|
|
# {{{ sub commands common options variables
|
|
local common_options_help=(
|
|
'(- :)--help[Show a help message and exit]'
|
|
)
|
|
local common_options_start=(
|
|
{-s,--start=}'[When the task starts]:DATE:__todo_date'
|
|
)
|
|
local common_options_due=(
|
|
{-d,--due=}'[When the task is due]:DATE:__todo_date'
|
|
)
|
|
local common_options_priority=(
|
|
'--priority=[The priority for this todo]:PRIORITY:("low" "medium" "high")'
|
|
)
|
|
local common_options_interactive=(
|
|
{-i,--interactive}'[Go into interactive mode before saving the task]'
|
|
)
|
|
local common_options_location=(
|
|
'--location=[The location where this todo takes place]:LOCATION:'
|
|
)
|
|
# }}}
|
|
# {{{ option helper: color mode
|
|
__color_mode(){
|
|
local modes=(
|
|
"always:enable regardless of stdout"
|
|
"auto:enable only when not on tty (default)"
|
|
"never:disable colored output entirely"
|
|
)
|
|
_describe "mode" modes
|
|
}
|
|
# }}}
|
|
# {{{ general helper: set variable of path to configuration file
|
|
__todo_set_conf(){
|
|
todoman_configuration_file=${XDG_CONFIG_DIR:-${HOME}/.config}/todoman/todoman.conf
|
|
if [[ -f $todoman_configuration_file ]]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
# }}}
|
|
# {{{ general helper: set variable main.path from configuration file
|
|
__todo_set_conf_path(){
|
|
if __todo_set_conf; then
|
|
tasks_lists_path="$(sed -n -e 's/^[^#]\s*path\s*=\s*\(.*\)$/\1/p' $todoman_configuration_file 2>/dev/null)"
|
|
# the eval echo is needed since the path may contain ~ which should be evalueated to $HOME
|
|
tasks_lists_dir="$(eval echo ${tasks_lists_path%/\**})"
|
|
if [[ -z "${tasks_lists_path}" || ! -d "${tasks_lists_dir}" ]]; then
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
# }}}
|
|
# {{{ general helper: set variables related to date and time formats for __todo_date
|
|
__todo_set_conf_dt(){
|
|
if __todo_set_conf; then
|
|
date_format="$(eval echo $(sed -n -e 's/^[^#]\s*date_format\s*=\s*\(.*\)$/\1/p' $todoman_configuration_file 2>/dev/null))"
|
|
dt_separator="$(eval echo $(sed -n -e 's/^[^#]\s*dt_separator\s*=\s*\(.*\)$/\1/p' $todoman_configuration_file 2>/dev/null))"
|
|
time_format="$(eval echo $(sed -n -e 's/^[^#]\s*time_format\s*=\s*\(.*\)$/\1/p' $todoman_configuration_file 2>/dev/null))"
|
|
# default value according to documentation: https://todoman.readthedocs.io/en/stable/configure.html
|
|
if [[ -z "${date_format}" ]]; then
|
|
date_format="%x"
|
|
fi
|
|
if [[ -z "${dt_separator}" ]]; then
|
|
dt_separator=""
|
|
fi
|
|
if [[ -z "${time_format}" ]]; then
|
|
time_format="%x"
|
|
fi
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
# }}}
|
|
# {{{ option helper: due and start date
|
|
__todo_date(){
|
|
if __todo_set_conf_dt; then
|
|
_message "date in format ${date_format//\%/%%}${dt_separator//\%/%%}${time_format//\%/%%}"
|
|
else
|
|
_message "date format (couldn't read configuration file and extract date and time formats)"
|
|
fi
|
|
}
|
|
# }}}
|
|
# {{{ argument helper: sub-command choice
|
|
__todo_command(){
|
|
local commands=(
|
|
'cancel:Cancel one or more tasks'
|
|
'copy:Copy tasks to another list'
|
|
'delete:Delete tasks'
|
|
'done:Mark one or more tasks as done'
|
|
'edit:Edit the task with id ID'
|
|
'flush:Delete done tasks'
|
|
'list:List tasks'
|
|
'move:Move tasks to another list'
|
|
'new:Create a new task with SUMMARY'
|
|
'show:Show details about a task'
|
|
)
|
|
_describe "command" commands
|
|
}
|
|
# }}}
|
|
# {{{ argument helper: available tasks choice
|
|
__todo_tasks(){
|
|
# checking if the command jq exists and it's version
|
|
# credit: http://stackoverflow.com/a/592649/4935114
|
|
jq_version=$(jq --version 2>/dev/null)
|
|
if [ ${${jq_version#jq\-}//./} -lt 15 ]; then
|
|
_message "we can't complete tasks unless you'll install the latest version of jq: https://stedolan.github.io/jq/"
|
|
return
|
|
fi
|
|
# $1 is a comma-seperated list of statuses to show when trying to complete this
|
|
local status_search_query="$1"
|
|
local -a tasks
|
|
IFS=$'\n'
|
|
for task_and_description in $(todo --porcelain list --status "${status_search_query}" | jq --raw-output '.[] | .id,":\"@",.list," ",.summary,"\"\\0"' | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n//g' -e 's/\\0/\n/g'); do
|
|
tasks+="$(eval echo ${task_and_description})"
|
|
done
|
|
_describe tasks tasks
|
|
}
|
|
# }}}
|
|
# {{{ todo available lists cache policy
|
|
__todo_lists_cache_policy(){
|
|
# the number of seconds since 1970-01-01 the directory
|
|
local tasks_lists_dir_last_date_modified="$(date -r ${tasks_lists_dir} +%s 2>/dev/null)"
|
|
# the number of seconds since 1970-01-01 the cache file was modified
|
|
local cache_last_date_modified="$(date -r $1 +%s 2>/dev/null)"
|
|
if [[ ! -z ${cache_last_date_modified} && ! -z ${tasks_lists_dir_last_date_modified} ]]; then
|
|
# if the manifest file is newer then the cache:
|
|
if [ ${tasks_lists_dir_last_date_modified} -ge ${cache_last_date_modified} ]; then
|
|
(( 1 ))
|
|
else
|
|
(( 0 ))
|
|
fi
|
|
else
|
|
(( 1 ))
|
|
fi
|
|
}
|
|
# }}}
|
|
# {{{ option helper: available lists
|
|
__todo_lists(){
|
|
if __todo_set_conf_path; then
|
|
local update_policy
|
|
zstyle -s ":completion:${curcontext}:" cache-policy update_policy
|
|
if [[ -z "$update_policy" ]]; then
|
|
zstyle ":completion:${curcontext}:" cache-policy __todo_lists_cache_policy
|
|
fi
|
|
local -a tasks_lists
|
|
if _cache_invalid todoman_lists; then
|
|
if [[ ${tasks_lists_path} =~ '/*$' ]]; then
|
|
for dir in $(eval echo ${tasks_lists_path}); do
|
|
if grep "VTODO" -q -R "${dir}"; then
|
|
list_name="${dir##*/}"
|
|
tasks_lists+=("${list_name}")
|
|
fi
|
|
done
|
|
fi
|
|
_store_cache todoman_lists tasks_lists
|
|
else
|
|
_retrieve_cache todoman_lists
|
|
fi
|
|
if [[ "${#tasks_lists[@]}" == 1 ]]; then
|
|
_message "only one list was detected: (\"${tasks_lists[1]}\")"
|
|
return
|
|
else
|
|
_describe "available lists" tasks_lists
|
|
return
|
|
fi
|
|
else
|
|
_message -e "no 'path = ' string was found in todoman's default configuration file ($todoman_configuration_file)"
|
|
return
|
|
fi
|
|
}
|
|
# }}}
|
|
# {{{ command `cancel`
|
|
_todo_cancel(){
|
|
_arguments \
|
|
"${common_options_help[@]}" \
|
|
'*: :{__todo_tasks "IN-PROCESS,NEEDS-ACTION"}'
|
|
}
|
|
# }}}
|
|
# {{{ command `copy`
|
|
local _command_copy_options=(
|
|
"${common_options_help[@]}"
|
|
{-l,--list=}'[The list to copy the tasks to]:TEXT:__todo_lists'
|
|
)
|
|
_todo_copy(){
|
|
_arguments \
|
|
"${_command_copy_options[@]}" \
|
|
'*: :{__todo_tasks "IN-PROCESS,NEEDS-ACTION"}'
|
|
}
|
|
# }}}
|
|
# {{{ command `delete`
|
|
local _command_delete_options=(
|
|
"${common_options_help[@]}"
|
|
"--yes[Don't ask for permission before deleting]"
|
|
)
|
|
_todo_delete(){
|
|
_arguments \
|
|
"${_command_delete_options[@]}" \
|
|
'*: :{__todo_tasks "IN-PROCESS,NEEDS-ACTION"}'
|
|
}
|
|
# }}}
|
|
# {{{ command `done`
|
|
local _command_done_options=(
|
|
"${common_options_help[@]}"
|
|
)
|
|
_todo_done(){
|
|
_arguments \
|
|
"${_command_done_options[@]}" \
|
|
'*: :{__todo_tasks "IN-PROCESS,NEEDS-ACTION"}'
|
|
}
|
|
# }}}
|
|
# {{{ command `edit`
|
|
local _command_edit_options=(
|
|
"${common_options_help[@]}"
|
|
"${common_options_start[@]}"
|
|
"${common_options_due[@]}"
|
|
"${common_options_priority[@]}"
|
|
"${common_options_location[@]}"
|
|
"${common_options_interactive[@]}"
|
|
)
|
|
_todo_edit(){
|
|
_arguments \
|
|
"${_command_edit_options[@]}" \
|
|
'*: :{__todo_tasks "IN-PROCESS,NEEDS-ACTION"}'
|
|
}
|
|
# }}}
|
|
# {{{ command `flush`
|
|
_todo_flush(){
|
|
}
|
|
# }}}
|
|
# {{{ command `list`
|
|
_command_list_options=(
|
|
"${common_options_location[@]}"
|
|
'--category=[Only show tasks with category containg TEXT]:TEXT:__todo_existing_categories'
|
|
'--grep=[Only show tasks with message containg TEXT]:TEXT:'
|
|
'--sort=[Sort tasks using these fields]:TEXT:(description location status summary uid rrule percent_complete priority sequence categories completed_at created_at dtstamp start due last_modified)'
|
|
'(--reverse --no-reverse)'{--reverse,--no-reverse}'[sort tasks in reverse order (see --sort)]'
|
|
"${common_options_start[@]}"
|
|
"${common_options_due[@]}"
|
|
'--priority[Only show tasks with priority at least as high as TEXT]:TEXT:("low", "medium", "high")'
|
|
'--startable[Show only todos which should can be started today]'
|
|
{-s,--status=}'[Show only todos with the provided comma-separated statuses]:STATUS:{_values -s , "status" "NEEDS-ACTION" "CANCELLED" "COMPLETED" "IN-PROCESS" "ANY"}'
|
|
"${common_options_help[@]}"
|
|
)
|
|
_todo_list(){
|
|
_arguments \
|
|
"${_command_list_options[@]}" \
|
|
'1: :__todo_lists' \
|
|
}
|
|
# }}}
|
|
# {{{ command `move`
|
|
_todo_move(){
|
|
_todo_copy
|
|
}
|
|
# }}}
|
|
# {{{ command `new`
|
|
local _command_new_options=(
|
|
"${common_options_start[@]}"
|
|
"${common_options_due[@]}"
|
|
"${common_options_help[@]}"
|
|
{-l,--list=}'[The list to move the tasks to]:TEXT:__todo_lists'
|
|
'--location[The location where this todo takes place.]:TEXT:__todo_existing_locations'
|
|
"${common_options_priority[@]}"
|
|
"${common_options_interactive[@]}"
|
|
)
|
|
_todo_new(){
|
|
_arguments \
|
|
"${_command_new_options[@]}" \
|
|
'*: :{_message "summary"}'
|
|
}
|
|
# }}}
|
|
# {{{ command `show`
|
|
_todo_show(){
|
|
_todo_done
|
|
}
|
|
# }}}
|
|
|
|
# The real thing
|
|
_arguments -C -A "-*" \
|
|
{-v,--verbosity=}'[Set verbosity to the given level]:MODE(CRITICAL ERROR WARNING INFO DEBUG)' \
|
|
'--color=[Set colored output mode]:MODE:__color_mode' \
|
|
'--porcelain[Use a JSON format that will remain stable regadless of configuration or version]' \
|
|
{-h,--humanize}'[Format all dates and times in a human friendly way]' \
|
|
'(- :)--version[Show the version and exit]' \
|
|
"${common_options_help[@]}" \
|
|
'1: :__todo_command' \
|
|
'*::arg:->args'
|
|
|
|
case $state in
|
|
(args)
|
|
curcontext="${curcontext%:*:*}:todo_$words[1]:"
|
|
case "${words[1]}" in
|
|
cancel)
|
|
_todo_cancel
|
|
;;
|
|
copy)
|
|
_todo_copy
|
|
;;
|
|
delete)
|
|
_todo_delete
|
|
;;
|
|
done)
|
|
_todo_done
|
|
;;
|
|
edit)
|
|
_todo_edit
|
|
;;
|
|
flush)
|
|
_todo_flush
|
|
;;
|
|
list)
|
|
_todo_list
|
|
;;
|
|
move)
|
|
_todo_move
|
|
;;
|
|
new)
|
|
_todo_new
|
|
;;
|
|
show)
|
|
_todo_show
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|