1#autoload
2
3# Usage: _deb_packages expl... avail|installed|uninstalled
4
5_deb_packages_update_avail () {
6  if ( [[ ${+_deb_packages_cache_avail} -eq 0 ]] ||
7      _cache_invalid DEBS_avail ) && ! _retrieve_cache DEBS_avail;
8  then
9    _deb_packages_cache_avail=(
10      ${(f)"$(apt-cache --generate pkgnames 2>/dev/null)"}
11    )
12
13    _store_cache DEBS_avail _deb_packages_cache_avail
14  fi
15  cachevar=_deb_packages_cache_avail
16}
17
18_deb_packages_update_installed () {
19  if ( [[ ${+_deb_packages_cache_installed} -eq 0 ]] ||
20      _cache_invalid DEBS_installed ) && ! _retrieve_cache DEBS_installed;
21  then
22    _deb_packages_cache_installed=()
23    dpkg --get-selections | while read package state ; do
24        [[ $state = (install|hold) ]] && _deb_packages_cache_installed+=$package
25    done
26    _store_cache DEBS_installed _deb_packages_cache_installed
27  fi
28  cachevar=_deb_packages_cache_installed
29}
30
31_deb_packages_update_held () {
32  if ( [[ ${+_deb_packages_cache_held} -eq 0 ]] ||
33      _cache_invalid DEBS_held ) && ! _retrieve_cache DEBS_held;
34  then
35    _deb_packages_cache_held=()
36    dpkg --get-selections | while read package state ; do
37        [[ $state = hold ]] && _deb_packages_cache_held+=$package
38    done
39    _store_cache DEBS_held _deb_packages_cache_held
40  fi
41  cachevar=_deb_packages_cache_held
42}
43
44_deb_packages_update_deinstalled () {
45  if ( [[ ${+_deb_packages_cache_deinstalled} -eq 0 ]] ||
46      _cache_invalid DEBS_deinstalled ) && ! _retrieve_cache DEBS_deinstalled;
47  then
48    _deb_packages_cache_deinstalled=()
49    dpkg --get-selections | while read package state ; do
50        [[ $state = deinstall ]] && _deb_packages_cache_deinstalled+=$package
51    done
52    _store_cache DEBS_deinstalled _deb_packages_cache_deinstalled
53  fi
54  cachevar=_deb_packages_cache_deinstalled
55}
56
57_deb_packages_update_xinstalled () {
58  if ( [[ ${+_deb_packages_cache_xinstalled} -eq 0 ]] ||
59      _cache_invalid DEBS_xinstalled ) && ! _retrieve_cache DEBS_xinstalled;
60  then
61    _deb_packages_cache_xinstalled=()
62    dpkg --get-selections | while read package state ; do
63        _deb_packages_cache_xinstalled+=$package
64    done
65    _store_cache DEBS_xinstalled _deb_packages_cache_xinstalled
66  fi
67  cachevar=_deb_packages_cache_xinstalled
68}
69
70_deb_packages_update_uninstalled () {
71  _deb_packages_update_avail
72  _deb_packages_update_installed
73  if (( ! $+_deb_packages_cache_uninstalled )); then
74    # Package lists too large to efficiently diff with zsh expansion
75    _deb_packages_cache_uninstalled=(
76      $( print -l $_deb_packages_cache_avail |
77         fgrep -xvf =(print -l $_deb_packages_cache_installed) )
78    )
79  fi
80  cachevar=_deb_packages_cache_uninstalled
81}
82
83_deb_packages () {
84  local command="$argv[$#]" expl cachevar pkgset update_policy
85
86  zstyle -s ":completion:*:*:$service:*" cache-policy update_policy
87  if [[ -z "$update_policy" ]]; then
88    zstyle ":completion:*:*:$service:*" cache-policy _debs_caching_policy
89  fi
90
91  [[ "$command" = (installed|deinstalled|xinstalled|held|uninstalled|avail|available) ]] || {
92    _message "unknown command: $command"
93    return
94  }
95
96  zstyle -s ":completion:${curcontext}:" packageset pkgset
97
98  [[ "$pkgset" = (installed|deinstalled|xinstalled|held|uninstalled|avail|available) ]] || {
99    pkgset="$command"
100  }
101
102  [[ "$pkgset" = "available" ]] && pkgset="avail"
103
104  expl=("${(@)argv[1,-2]}")
105
106  _deb_packages_update_$pkgset
107
108  typeset -gH $cachevar
109
110  _tags packages && compadd "$expl[@]" - "${(@P)cachevar}"
111}
112
113_debs_caching_policy () {
114  # rebuild if cache is more than a week old
115  local -a oldp
116  oldp=( "$1"(mw+1) )
117  (( $#oldp )) && return 0
118
119  [[ /var/cache/apt/pkgcache.bin -nt "$1" ||
120     /var/lib/dpkg/available -nt "$1" ]]
121}
122
123_deb_packages "$@"
124