1#autoload
2
3_mailboxes() {
4  #emulate -L zsh
5  local expl ret=1
6  local maildirectory pinedirectory
7  zstyle -s ":completion:${curcontext}:" mail-directory maildirectory || maildirectory="~/Mail"
8  zstyle -s ":completion:${curcontext}:" pine-directory pinedirectory
9
10  if (( ! $+_mailbox_cache )) then
11    _mailbox_cache "$@"
12  fi
13
14  case "${curcontext}:" in
15    (*:mail:*)
16      if [[ "$PREFIX" == +* ]]; then
17	_tags mailboxes
18      else
19        _tags mailboxes files
20      fi;;
21    (*:(mush|zmail|zmlite):*)
22      if [[ "$PREFIX" == [%+]* ]]; then
23	_tags mailboxes
24      else
25        _tags mailboxes files
26      fi;;
27    (*:mutt:*)
28      if [[ "$PREFIX" == (|-f)[+=]* ]]; then
29	_tags mailboxes
30      else
31        _tags mailboxes files
32      fi;;
33    (*:pine:*)
34      # Files for pine must be absolute paths.
35      if [[ "$PREFIX" == (|-f)[/\~]* ]]; then
36        pinedirectory=''
37        _tags mailboxes files
38      else
39        _tags mailboxes
40      fi;;
41    (*)
42      if [[ "$PREFIX" == (|-f)+* ]]; then
43	_tags mailboxes
44      else
45        _tags mailboxes files
46      fi;;
47  esac
48
49  while _tags; do
50    _requested mailboxes expl 'mailbox specification' _mua_mailboxes && ret=0
51
52    if _requested files expl 'mailbox file'; then
53      [[ "${curcontext}:" != *:(mail|mush|mutt|zmail|zmlite):* ]] &&
54	compset -P -f
55      _files "$expl[@]" && ret=0
56    fi
57    (( ret )) || return 0
58  done
59
60  return 1
61}
62
63_mailbox_cache () {
64  local i j _mc_tmp
65  local -aU dirboxes
66  local maildirectory pinedirectory muttrc
67  typeset -aU -g _mailbox_cache
68  typeset -aU -g _maildir_cache _mbox_cache _mh_cache _mutt_cache _pine_cache
69
70  zstyle -s ":completion:${curcontext}:" mail-directory maildirectory || maildirectory="~/Mail"
71  zstyle -s ":completion:${curcontext}:" pine-directory pinedirectory
72  zstyle -s ":completion:${curcontext}:" muttrc muttrc || muttrc="~/.muttrc"
73
74  [[ -f ${~muttrc:-.} ]] &&
75    _mc_tmp=${=${(M)${(f)"$(<${~muttrc})"}:#mailboxes *}#mailboxes *} &&
76    _mutt_cache=( ${=${(Xe)_mc_tmp}} )
77
78  _mbox_cache=( ${~maildirectory}/*(^/) )
79  if [[ -n $pinedirectory ]]; then
80    _pine_cache=( ${~pinedirectory}/**/*(.) )
81  else
82    _pine_cache=()
83  fi
84
85  dirboxes=( ${~maildirectory}/*(/) )
86
87  while (( $#dirboxes )); do
88    i=${dirboxes[1]}
89    shift dirboxes
90    if [[ -d "$i/cur" ]]; then
91      _maildir_cache=( "${_maildir_cache[@]}" "$i" )
92    elif j=( "$i"/<1-> ) && [[ -n "$j" ]]; then
93      _mh_cache=( "${_mh_cache[@]}" "$i" )
94      dirboxes=( $dirboxes "$i"/*(/) )
95    else
96      _mbox_cache=( "${_mbox_cache[@]}" "$i"/*(.) )
97      dirboxes=( $dirboxes "$i"/*(/) )
98    fi
99  done
100
101  [[ -n "$mailpath" ]] &&
102      _mailbox_cache=( "${_mailbox_cache[@]}" "${(@)mailpath%%\?*}" )
103
104  [[ -n "$MAIL" ]] && _mailbox_cache=( "${_mailbox_cache[@]}" $MAIL )
105}
106
107_mua_mailboxes() {
108  local -a mbox_short
109  local -aU mbox_names
110  local ret=1
111
112  local maildirectory pinedirectory
113  zstyle -s ":completion:${curcontext}:" mail-directory maildirectory || maildirectory="~/Mail"
114  zstyle -s ":completion:${curcontext}:" pine-directory pinedirectory
115
116  case "${curcontext}:" in
117    (*:elm:*) # I've probably got this wrong, or at least incomplete
118      mbox_names=( "${_mbox_cache[@]}" "${_mailbox_cache[@]}" )
119      mbox_short=( \! \< \> )
120      ;;
121    (*:mail:*)
122      if compset -P +; then
123        mbox_names=( "${(@)_mbox_cache#$~maildirectory/}" )
124      else
125        mbox_names=( +"${(@)^_mbox_cache#$~maildirectory/}"
126		    "${_mailbox_cache[@]}" )
127      fi
128      ;;
129    (*:mh:*)
130      local lastmhbox=$(mhpath)
131      if compset -P +; then
132	mbox_names=( "${(@)_mh_cache#$~maildirectory/}" )
133      elif compset -P @; then
134	mbox_names=( "${(@)${(@M)_mh_cache:#$~lastmhbox/*}#$~lastmhbox/}" )
135      else
136	mbox_names=( +"${(@)^_mh_cache#$~maildirectory/}"
137		     @"${(@)^${(@M)_mh_cache:#$~lastmhbox/*}#$~lastmhbox/}"
138		     "${_mh_cache[@]}" )
139      fi
140      ;;
141    (*:mush:*)
142      if compset -P %; then
143        mbox_short=( "${(@k)userdirs}" )
144      elif compset -P +; then
145        mbox_names=( "${(@)_mbox_cache#$~maildirectory/}" )
146      else
147        mbox_names=( +"${(@)^_mbox_cache#$~maildirectory/}"
148		     "${_mailbox_cache[@]}" )
149        mbox_short=( \& % %"${(@k)^userdirs}" )
150      fi
151      ;;
152    (*:mutt:*)
153      if compset -P '(|\\)='; then
154        mbox_names=( "${_mutt_cache[@]#[+=]}" "${(@)_mbox_cache#$~maildirectory/}" "${(@)_maildir_cache#$~maildirectory/}" "${(@)_mh_cache#$~maildirectory/}")
155      elif compset -P +; then
156        mbox_names=( "${_mutt_cache[@]#[+=]}" "${(@)_mbox_cache#$~maildirectory/}" "${(@)_maildir_cache#$~maildirectory/}" "${(@)_mh_cache#$~maildirectory/}")
157      else
158      mbox_names=( "${_mutt_cache[@]}" "${_mailbox_cache[@]}"
159		   "${_maildir_cache[@]}" "${_mh_cache[@]}" )
160      mbox_short=( \! \< \> )
161      fi
162      ;;
163    (*:pine:*)
164      mbox_names=( "${_mbox_cache[@]}"
165		   "${_mailbox_cache[@]}" "${_mh_cache[@]}" )
166      # Pine is like mail but with no leading `+' to disambiguate;
167      # any files not in $pinedirectory must be absolute paths.
168      if [[ -n $pinedirectory ]]; then
169	mbox_names+=( "${(@)_pine_cache#$~pinedirectory/}" )
170      fi
171      ;;
172    (*:tkrat:*) # Has a couple of custom formats I haven't programmed for.
173      mbox_names=( "${_mbox_cache[@]}"
174		   "${_mailbox_cache[@]}" "${_mh_cache[@]}" )
175      ;;
176    (*:(zmail|zmlite):*)
177      if compset -P %; then
178        mbox_short=( "${(@k)userdirs}" )
179      elif compset -P +; then
180        mbox_names=( "${(@)_mbox_cache#$~maildirectory/}" )
181      else
182        mbox_names=( +"${(@)^_mbox_cache#$~maildirectory/}"
183		     "${_mailbox_cache[@]}" "${_mh_cache[@]}" )
184        mbox_short=( \& % %"${(@k)^userdirs}" )
185      fi
186      ;;
187    (*) # Some other program wants mailbox names?  Use them all?
188       mbox_names=( "${_mailbox_cache[@]}" "${_mbox_cache[@]}"
189		    "${_mh_cache[@]}" "${_mutt_cache[@]}" "${_pine_cache[@]}" )
190       ;;
191  esac
192
193  (( $#mbox_names )) && _multi_parts "$@" / mbox_names && ret=0
194  (( $#mbox_short )) && compadd "$@" -a mbox_short && ret=0
195  return ret
196}
197
198_mailboxes "$@"
199