#compdef eix eix-diff eix-update
local curcontext="$curcontext" state state_descr line expl
typeset -A opt_args

local service_opts excl_opt ret i
local -x PRINT_APPEND=

# Options common to diff-eix and eix
service_opts=(
{'(--quick)-Q','(-Q)--quick'}'[do not try to read unguessable slots]'
'--care[always read slots of installed packages]'
'--deps-installed[always read deps of installed packages]'
'--ansi[reset the ansi 256 color palette]'
)

case $service in
(*update*)
  excl_opt='(-)'
  service_opts=(
'(--force-status '{'--nostatus)-H','-H)--nostatus'}'[do not update status line]'
'(--nostatus -H)--force-status[force status line on non-terminal]'
{'(--output)-o+','(-o)--output'}'[output to FILE]:output_file:_files'
{'*--exclude-overlay','*-x+'}'[OVERLAY (exclude)]:exclude overlay:->overlay'
{'*--add-overlay','*-a+'}'[OVERLAY (add)]:add overlay:_files -/'
{'*--override-method','*-m+'}'[OVERLAY_MASK METHOD (override method)]:overlay mask to change method:->overlay:cache method: '
{'*--repo-name','*-r+'}'[OVERLAY REPO_NAME (set REPO_NAME for OVERLAY)]:overlay to change name:->overlay:repo-name: '
);;
(*diff*)
  excl_opt='(1 2 -)'
  service_opts+=(
'1:old_cache:_files'
'2::new_cache:_files'
);;
(*)
  excl_opt='(* -)'
  service_opts+=(
"$excl_opt"'--print-all-useflags[print all IUSE words]'
"$excl_opt"'--print-all-keywords[print all KEYWORDS words]'
"$excl_opt"'--print-all-slots[print all SLOT strings]'
"$excl_opt"'--print-all-licenses[print all LICENSE strings]'
"$excl_opt"'--print-all-depends[print all *DEPEND words]'
"$excl_opt"'--print-world-sets[print the world sets]'
"$excl_opt"'--print-profile-paths[print the profile paths]'
"$excl_opt"'--256[print all ansi color palettes]'
"$excl_opt"'--256l[print light ansi color palettes]'
"$excl_opt"'--256l0[print light ansi color palette (normal)]'
"$excl_opt"'--256l1[print light ansi color palette (bright)]'
"$excl_opt"'--256d[print dark ansi color palettes]'
"$excl_opt"'--256d0[print dark ansi color palette (normal)]'
"$excl_opt"'--256d1[print dark ansi color palette (bright)]'
"$excl_opt"'--256b[print ansi color palette for background]'
{'(--remote)-R','(-R)--remote'}'[use remote database 1]'
{'(--remote2)-Z','(-Z)--remote2'}'[use remote database 2]'
{'(--versionsort)-x','(-x)--versionsort'}'[sort output by slots/versions]'
{'(--versionlines)-l','(-l)--versionlines'}'[output versions line by line]'
{'(--compact)-c','(-c)--compact'}'[use \$FORMAT_COMPACT]'
{'(--verbose)-v','(-v)--verbose'}'[use \$FORMAT_VERBOSE]'
'--xml[output in xml format]'
{'(--pure-packages)-\\*','(-\\*)--pure-packages'}'[omit printing of overlay names and package number]'
{'(--only-names)-#','(-#)--only-names'}'[print with format \<category\>/\<name\>]'
{'(--brief)-0','(-0)--brief'}'[print at most one package]'
'--brief2[print at most two packages]'
{'(--test-non-matching)-t','(-t)--test-non-matching'}'[check /etc/portage/package.* and installed packages]'
'--cache-file[CACHE_FILE (use instead of /var/cache/eix/portage.eix)]:cache-file:_files'
'--format[FORMAT]:format: '
'--format-compact[FORMAT_COMPACT]:format_compact: '
'--format-verbose[FORMAT_VERBOSE]:format_verbose: '
{'*--not','*-\!'}'[logical negation]'
{'*--and','*-a'}'[logical disjunction]'
{'*--or','*-o'}'[logical conjunction]'
{'*--open','*-\('}'[logical opening brace]'
{'*--close','*-\)'}'[logical closing brace]'
{'*--installed','*-I'}'[test for installed packages]'
{'*--multi-installed','*-i'}'[test for multiple installed packages]'
{'*--dup-packages','*-d'}'[test for duplicate packages]'
{'*--dup-versions','*-D'}'[test for duplicated versions]'
{'*--slotted','*-1'}'[test for nontrivial slots]'
{'*--slots','*-2'}'[test for multiple slots]'
{'*--upgrade','*-u'}'[test for upgradable packages]'
'*--upgrade\+[test for upgradable packages, local]'
'*--upgrade\-[test for upgradable packages, non-local]'
'*--stable[test for stable packages]'
'*--stable+[test for stable packages, local]'
'*--stable-[test for stable packages, non-local]'
'*--testing[test for testing packages]'
'*--testing+[test for testing packages, local]'
'*--testing-[test for testing packages, non-local]'
'*--non-masked[test for non-masked packages]'
'*--non-masked+[test for non-masked packages, local]'
'*--non-masked-[test for non-masked packages, non-local]'
'*--system[test for @system packages]'
'*--system+[test for @system packages, local]'
'*--system-[test for @system packages, non-local]'
'*--installed-unstable[test for installed unstable packages]'
'*--installed-testing[test for installed testing packages]'
'*--installed-masked[test for installed masked packages]'
'*--world[test for @world packages]'
'*--world-file[test for @world-file packages]'
'*--world-set[test for @world-set packages]'
'*--selected[test for @selected packages]'
'*--selected-file[test for @selected-file packages]'
'*--selected-set[test for @selected-set packages]'
'*--binary[test for packages with .tbz2/.xpak]'
'*--multi-binary[NR (test for at least NR of .tbz2/.xpak)]::minimal binaries:(1 2 3 4 5 6 7 8 9)'
{'*--overlay','*-O'}'[test if package is in an overlay]'
'*--in-overlay[OVERLAY (test for packages in OVERLAY)]:overlay for testing:->overlay'
'*--only-in-overlay[OVERLAY (test for packages only in OVERLAY)]:overlay (only) for testing:->overlay'
{'*--installed-overlay','*-J'}'[test if package is installed from an overlay]'
'*--installed-from-overlay[OVERLAY (test for package installed from OVERLAY)]:overlay (installed) for testing:->overlay'
'*--installed-in-overlay[OVERLAY (test for package installed and in OVERLAY)]:overlay (installed and in) for testing:->overlay'
'*--installed-in-some-overlay[test for package installed and in some overlay]'
'*--restrict-fetch[test for RESTRICT=fetch packages]'
'*--restrict-mirror[test for RESTRICT=mirror packages]'
'*--restrict-primaryuri[test for RESTRICT=primaryuri packages]'
'*--restrict-binchecks[test for RESTRICT=binchecks packages]'
'*--restrict-strip[test for RESTRICT=strip packages]'
'*--restrict-test[test for RESTRICT=test packages]'
'*--restrict-userpriv[test for RESTRICT=userpriv packages]'
'*--restrict-installsources[test for RESTRICT=installsources packages]'
'*--restrict-bindist[test for RESTRICT=bindist packages]'
'*--restrict-parallel[test for RESTRICT=parallel packages]'
'*--properties-interactive[test for PROPERTIES=interactive packages]'
'*--properties-live[test for PROPERTIES=live packages]'
'*--properties-virtual[test for PROPERTIES=virtual packages]'
'*--properties-set[test for PROPERTIES=set packages]'
{'*--test-obsolete','*-T'}'[test for packages with obsolete /etc/portage/package.*]'
{'*--pipe','*-\|'}'[test for packages/versions matching stdin]'
'*--pipe-name[test for packages matching stdin]'
'*--pipe-version[test for versions matching stdin]'
{'*--name','*-s'}'[match name]'
{'*--description','*-S'}'[match description]'
{'*--category','*-C'}'[match category]'
{'*--category-name','*-A'}'[match "category/name"]'
{'*--homepage','*-H'}'[match homepage]'
{'*--license','*-L'}'[match license]'
{'*--use','*-U'}'[match IUSE]'
{'*--any','*-y'}'[match any field (same as -SACsHL...)]'
'*--deps[match *DEPEND]'
'*--depend[match DEPEND]'
'*--rdepend[match RDEPEND]'
'*--pdepend[match PDEPEND]'
'*--bdepend[match BDEPEND]'
'*--idepend[match IDEPEND]'
'*--set[match setname]'
'*--eapi[match EAPI]'
'*--installed-eapi[match installed EAPI]'
'*--slot[match slotname]'
'*--installed-slot[match installed slotname]'
'*--installed-with-use[match installed enabled USE]'
'*--installed-without-use[match installed disabled USE]'
{'*--exact','*-e'}'[pattern is exact string]'
{'*--begin','*-b'}'[pattern is beginning of string]'
'*--end[pattern is end of string]'
{'*--substring','*-z'}'[pattern is substring]'
{'*--fuzzy','*-f+'}'[N (pattern is fuzzy, Levenshtein N)]::number (Levenshtein distance):(1 2 3 4 5 6 7 8 9)'
{'*--pattern','*-p'}'[pattern is wildcard pattern]'
{'*--regex','*-r'}'[pattern is regular expression, ignoring case]'
'*--regex-case[pattern is regular expression, using case]'
)
# find out search field and whether to check only installed packages
  local c w is_or local field= installed=
  if ((CURRENT>2)); then
    is_or=:
    case $(_call_program default_is_or 'eix --print DEFAULT_IS_OR 2>/dev/null') in
    (''|[nNfF]*|[oO][fF]*|0|-)
      is_or=false;;
    esac
    for ((i=2;i<CURRENT;++i)); do
      case $words[i] in
      (--)
        i=$CURRENT;;
      (--cache-file|--format(-compact|-verbose|)|--(only-|)in-overlay|--installed-(from|in)-overlay|--fuzzy|--print)
        ((++i));;
      (--not|--open|--close|---*|[!-])
        if $is_or; then
          field=
          installed=
        fi;;
      (--(multi-|)installed)
        installed='installed';;
      (--category|--name|--description|--homepage|--license)
        field=${words[i]#--};;
      (--category-name)
        field='category/name';;
      (--use|--installed-with(out|)-use)
        field='useflag';;
      (--depend)
        field='depend';;
      (--rdepend)
        field='rdepend';;
      (--pdepend)
        field='pdepend';;
      (--bdepend)
        field='bdepend';;
      (--idepend)
        field='idepend';;
      (--deps)
        field='deps';;
      (--set)
        field='set';;
      (--eapi)
        field='eapi';;
      (--installed-eapi)
        installed='installed'
        field='eapi';;
      (--slot)
        field='slot';;
      (--installed-slot)
        installed='installed'
        field='slot';;
      (-[!-]*)
        w=$words[$i]
        for ((c=2;c<=$#w;++c)); do
          case $w[c] in
          ([f])
            if ((c==$#w)); then
              ((++i))
            else
              c=$#w
            fi;;
          ([\(\)!])
            if $is_or; then
              field=
              installed=
            fi;;
          ([iI])
            installed='installed';;
          (C)
            field='category';;
          (s)
            field='name';;
          (S)
            field='description';;
          (A)
            field='category/name';;
          (H)
            field='homepage';;
          (L)
            field='license';;
          esac
        done;;
      esac
    done
  fi
  : ${field:='package'}
  i=($installed $field)
  service_opts+=(
'*:'"$i"':->args'
);;
esac
_arguments -C -s -S : \
"$excl_opt"{'--help','-h'}'[help]' \
"$excl_opt"{'--version','-v'}'[version]' \
"$excl_opt"'--print[print expanded variable value]:variable:->vars' \
"$excl_opt"'--dump[dump variables]' \
"$excl_opt"'--dump-defaults[dump default values of variables]' \
{'(--quiet)-q','(-q)--quiet'}'[no output]' \
'(--force-color -F '{'--nocolor)-n','-n)--nocolor'}'[do not use colors in output]' \
'(--nocolor -n '{'--force-color)-F','-F)--force-color'}'[force color on non-terminal]' \
$service_opts
ret=$?
case $state in
(vars)
  _tags variables
  _tags && {
    _description variables expl 'eix variable name'
    compadd "$expl[@]" - ${(f)"$(_call_program $service-known-vars \
        '$service --known-vars 2>/dev/null')"}
  } && ret=0;;
(overlay)
  _tags overlays
  _tags && {
    local -ua o
    o=($(_call_program portdir_overlay \
        'eix --print PORTDIR_OVERLAY 2>/dev/null'))
    o+=("$(_call_program portdir 'eix --print PORTDIR 2>/dev/null')")
    o+=({0..$#o})
    _description overlays expl 'overlay'
    compadd "$expl[@]" - $o
  } && ret=0;;
(args)
  local -a eixopt
  eixopt=('--pure-packages')
  [[ -z $installed ]] || eixopt+=('-I')
  local -x NEWLINE=false CAREMODE=false QUICKMODE=true FORCE_COLORS=false \
    RESTRICT_INSTALLED=false USE_BUILD_TIME=false
  case $field in
  (category)
    _tags categories
    _tags && {
      _description categories expl 'package category'
      compadd "$expl[@]" - $(_call_program packages${installed:+-installed} \
          "eix \$eixopt --format '<category>\\n' 2>/dev/null")
    } && ret=0;;
  (name)
    _tags packages
    _tags && {
      _description packages expl 'package name'
      compadd "$expl[@]" - $(_call_program packages${installed:+-installed} \
          "eix \$eixopt --format '<name>\\n' 2>/dev/null")
    } && ret=0;;
  (category/name)
    _tags packages
    _tags && {
      _description packages expl 'category/name'
      compadd "$expl[@]" - $(_call_program packages${installed:+-installed} \
          "eix \$eixopt --format '<category>/<name>\\n' 2>/dev/null")
    } && ret=0;;
  (package)
    _tags packages
    _tags && case $PREFIX in
    (*/*)
      _description packages expl 'category/name'
      i=${PREFIX%/*}
      compset -P '*/'
      compadd "$expl[@]" - $(_call_program \
          packages-category${installed:+-installed} \
          "eix \$eixopt -C \"\$i\" --format '<name>\\n' 2>/dev/null");;
    (*)
      _description packages expl 'package'
      i=($(_call_program packages${installed:+-installed} \
          "eix \$eixopt --format '<category>/<name>\\n' 2>/dev/null"))
      compadd "$expl[@]" - ${i:t} || {
        _description packages expl 'category/name'
        compadd "$expl[@]" - ${i%%/*}/
      }
    esac && ret=0;;
  (useflag)
    _tags useflags
    _tags && {
      _description useflags expl 'useflag'
      compadd "${expl[@]}" - ${$(_call_program useflags \
          'eix --print-all-useflags 2>/dev/null')##[()+-]#}
    } && ret=0;;
  (license)
    _tags licenses
    _tags && {
      _description licenses expl 'license'
      compadd "${expl[@]}" - ${$(_call_program licenses \
          'eix --print-all-licenses 2>/dev/null')//([\(\)\|]|[![:space:]]#\?)/}
    } && ret=0;;
  (eapi)
    _tags slots
    _tags && {
      _description slots expl 'eapi'
      compadd "${expl[@]}" - $(_call_program slots \
          'eix --print-all-eapis 2>/dev/null')
    } && ret=0;;
  (slot)
    _tags slots
    _tags && {
      _description slots expl 'slot'
      compadd "${expl[@]}" - $(_call_program slots \
          'eix --print-all-slots 2>/dev/null')
    } && ret=0;;
  (homepage)
    _tags homepages
    _tags && {
      _description homepages expl 'homepage'
      compadd "${expl[@]}" - $(_call_program homepages \
          "eix \$eixopt --format '<homepage>\\n' 2>/dev/null")
    } && ret=0;;
  (set)
    _tags sets
    _tags && () {
      local -ua o
      local portdir j k
      local -a sets
      o=($(_call_program portdir_overlay \
          'eix --print PORTDIR_OVERLAY 2>/dev/null'))
      portdir=$(_call_program portdir 'eix --print PORTDIR 2>/dev/null')
      sets=()
      for i in ${="$(_call_program eix_local_sets \
          'eix --print EIX_LOCAL_SETS 2>/dev/null')"}; do
      case $i in
        (/*)
          [[ -d $i ]] && sets+=($i);;
        ('*'*)
          k=${i#'*'}
          for j in $o; do
            [[ -d "$j$k" ]] && sets+=("$j$k")
          done;;
        (*)  [[ -d "$portdir$i" ]] && sets+=("$portdir$i");;
        esac
      done
      if (($#sets)); then
        _description sets expl 'set'
        compadd "${expl[@]}" - ${${(f)"$(_call_program sets \
            'find -L $sets -type f -name "[!.]*" -print 2>/dev/null')"}:t}
      fi
    } && ret=0;;
  esac;;
esac
return ret
