diff --git a/src/_pytest b/src/_pytest new file mode 100644 index 0000000..a337dd9 --- /dev/null +++ b/src/_pytest @@ -0,0 +1,112 @@ +#compdef pytest py.test + +local ret=1 + +local context state state_descr line +typeset -A opt_args + + +_pytest_caching_policy () { + # rebuild if cache is more than a week old + local -a oldp + oldp=( "$1"(Nm+7) ) + (( $#oldp )) +} + +local -a pytest_options +_pytest_options() { + # this function calls py.test and loops over the list of apps and options + # and constructs the help menu with it + + local cache_policy + zstyle -s ":completion:${curcontext}:" cache-policy cache_policy + if [[ -z "$cache_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy _pytest_caching_policy + fi + + if _cache_invalid pytest_options || ! _retrieve_cache pytest_options; then + zle -M "Querying pytest options..." + + # TODO: + # - start sections with '^reporting:' etc. + + local line + local _words opts i desc + local opt + local in_desc + _call_program commands py.test --help | while IFS='' read line; do + # add dashed options for completion only + if [[ $line[1,3] == ' -' ]] || [[ -z "$line" ]]; then + + desc="${(L)desc[1]}${desc[2,-1]}" + desc="${desc%.}" + if (( $#opts )); then + if (( $#opts > 1 )); then + for opt in $opts; do + pytest_options+=("(${opts})${opt}[${desc}]") + done + else + pytest_options+=("${opts}[$desc]") + fi + fi + + opts=() + desc= + in_desc=0 + [[ -z "$line" ]] && continue + elif (( in_desc )); then + shortdesc=${line## #} + # TODO: punctuation + # if [[ "$shortdesc" != "$desc" ]]; then + # in_desc=0 + # fi + desc="$desc ${${shortdesc:gs/[/\\[}:gs/]/\\]}" + continue + fi + + _words=($=line) + # [[ ${_words[1][1]} == '-' ]] || continue + + i=0 + for w in $_words; do + (( i++ )) + if [[ $w[1] == '-' ]]; then + opt="${w%,}" + # Remove `=` operator example values from the help output + opt="${opt%%=*}" + + # -k is defined manually. + [[ "$opt" == "-k" ]] && break + opts+=($opt) + else + desc=${_words[i,-1]} + if [[ -z "$desc" ]]; then + in_desc=1 + break + fi + desc=${${desc:gs/[/\\[}:gs/]/\\]} + in_desc=1 + # TODO: do not split on "e.g.": look at end and ". " only?! + # shortdesc=${desc%%.*} + # if [[ "$shortdesc" == "$desc" ]]; then + # in_desc=1 + # fi + # desc="$shortdesc" + break + fi + done + done + pytest_options+=('-k[only run tests matching the substring expression]:tag:_complete_tag') + _store_cache pytest_options pytest_options + fi +} + +_pytest_options + +_arguments -C \ + ':file:_files' \ + $pytest_options \ + '*::options:->options' && ret=0 + _pytest_options + +return $ret