#compdef atag
# vim:ft=zsh:fdm=marker
###
### Frank Terbeck <ft@bewatermyfriend.org>
### Last-Modified: Fri Mar  7 10:34:04 2008
###
### URI: <http://ft.bewatermyfriend.org/comp/zsh.html>
###

setopt localoptions noksharrays

local astate
local -i need_arguments
local -a arguments_args arguments_file desc_strs supported_extensions
local -A desc

# tag definition names with descriptions {{{
desc=(
    'album'         "album name"
    'artist'        "artist name"
    'compilation'   "compilation name"
    'genre'         "content type"
    'year'          "release date"
    'tracktitle'    "track title"
    'tracknumber'   "track number"
)

desc_strs=(
    "\"al=:${desc[album]}\""
    "\"album=:${desc[album]}\""
    "\"ar=:${desc[artist]}\""
    "\"artist=:${desc[artist]}\""
    "\"comp=:${desc[compilation]}\""
    "\"compilation=:${desc[compilation]}\""
    "\"g=:${desc[genre]}\""
    "\"genre=:${desc[genre]}\""
    "\"y=:${desc[year]}\""
    "\"year=:${desc[year]}\""
    "\"tt=:${desc[tracktitle]}\""
    "\"tracktitle=:${desc[tracktitle]}\""
    "\"tn=:${desc[tracknumber]}\""
    "\"tracknumber=:${desc[tracknumber]}\""
)
#}}}

arguments_args=(
# arguments to _arguments, see below {{{
    '-d[dryrun, just print what would be done]'
    '-e[export, set shell variables to tag values of current file]'
    '-f[force, clear all tag before setting new ones]'
    '*::tag definitions:_atag_tags'
#}}}
)

arguments_file=(
# arguments to _arguments, see below {{{
    '-F[list features, which depend on external programs]'
    '-L[list where the needed external programs can be found]'
    '*::files:_atag_files'
#}}}
)

supported_extensions=(
# file extensions, atag can handle. used for file completion {{{
    'mp3'
    'ogg'
    'flac'
#}}}
)

function _atag_files() {
# shorthand for our _path_files call {{{
    _path_files -g "(#i)*.(${(j:|:)supported_extensions})" -g "*(-/)"
#}}}
}

function _atag_tags() {
    # generating tag definition names as completions {{{
    local expl tag

    _describe 'tag definitions' '( '${(j: :)desc_strs}' )' -S ''
    #}}}
}

# The way atag is called is a bit non-standard. The first argument is
# the filename, which is going to be processed. In order to help
# _arguments to deal with this, rip away the 2nd element from $words.
# Setting an own state value in order to be able to complete filenames
# as well.
if (( CURRENT == 2 )) ; then
    astate='file'
else
    astate='args'
    words[2]=()
    (( CURRENT-- ))
fi

case ${astate} in
    # handling our states {{{
    (file)
        _arguments -s ${arguments_file} ;;
    (args)
        # check if we are already in a tag definition {{{
        (( need_arguments = 0 ))
        case ${words[$CURRENT]} in
            ((#b)(al|album)=*)
                _message ${desc[album]} ;;
            ((#b)(ar|artist)=*)
                _message ${desc[artist]} ;;
            ((#b)(y|year)=*)
                _message ${desc[year]} ;;
            ((#b)(comp|compilation)=*)
                _message ${desc[compilation]} ;;
            ((#b)g(|enre)=*)
                _message ${desc[genre]} ;;
            ((#b)(tn|tracknumber)=*)
                _message ${desc[tracknumber]} ;;
            ((#b)(tt|tracktitle)=*)
                _message ${desc[tracktitle]} ;;
            (*)
                (( need_arguments = 1 )) ;;
        esac

        (( need_arguments == 0 )) && return 0
        #}}}

        # if not, complete options and tag definition names
        _arguments -s ${arguments_args}
        ;;
    #}}}
esac