about summary refs log tree commit diff
path: root/Completion/User/_mailboxes
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/User/_mailboxes')
-rw-r--r--Completion/User/_mailboxes174
1 files changed, 153 insertions, 21 deletions
diff --git a/Completion/User/_mailboxes b/Completion/User/_mailboxes
index c49aa8185..e2b4b5289 100644
--- a/Completion/User/_mailboxes
+++ b/Completion/User/_mailboxes
@@ -1,32 +1,164 @@
 #autoload
 
-# This is needlessly mutt-biased and should be fixed.
+_mailboxes() {
+  #emulate -L zsh
+  local expl ret=1
+  local pinedirectory="${pinedirectory:-~/mail}"
+  local maildirectory="${maildirectory:-~/Mail}"
 
-local expl muttboxes mboxes dirboxes MHboxes maildirboxes muttrc="~/.muttrc" maildirectory="~/Mail"
+  if (( ! $+_mailbox_cache )) then
+    _mailbox_cache "$@"
+  fi
 
-test -f "$compconfig[muttrc_path]" && muttrc=$compconfig[muttrc_path]
-test -f "$compconfig[maildirectory]" && maildirectory=$compconfig[maildirectory]
+  case "${curcontext}" in
+    (*:mail:*)
+      if [[ "$PREFIX" == +* ]]; then
+	_tags mailboxes
+      else
+        _tags mailboxes files
+      fi;;
+    (*:(mush|zmail|zmlite):*)
+      if [[ "$PREFIX" == [%+]* ]]; then
+	_tags mailboxes
+      else
+        _tags mailboxes files
+      fi;;
+    (*:pine:*)
+      # Files for pine must be absolute paths.
+      if [[ "$PREFIX" == (|-f)[/\~]* ]]; then
+        pinedirectory=''
+        _tags mailboxes files
+      else
+        _tags mailboxes
+      fi;;
+    (*)
+      if [[ "$PREFIX" == (|-f)+* ]]; then
+	_tags mailboxes
+      else
+        _tags mailboxes files
+      fi;;
+  esac
 
-if (( ! $+_mailbox_cache )) then
+  while _tags; do
+    _requested mailboxes expl 'mailbox specification' _mua_mailboxes && ret=0
 
-test ${muttrc} || test -f ${~muttrc} && muttboxes=( ${(@)$(grep mailboxes ${~muttrc})[2,-1]} )
+    if _requested files expl 'mailbox file'; then
+      [[ "${curcontext}" != *:(mail|mush|zmail|zmlite):* ]] &&
+	compset -P -f
+      _files "$expl[@]" && ret=0
+    fi
+    (( ret )) || return 0
+  done
 
-mboxes=(${~maildirectory}/*(^/))
-dirboxes=(${~maildirectory}/*(/))
+  return 1
+}
 
-for i in $dirboxes
-do 
-if test -d "${i}/cur"
-then
-maildirboxes=($maildirboxes $i)
-else
-MHboxes=($MHboxes $i)
-fi
-done
+_mailbox_cache () {
+  # Depends on $maildirectory and $pinedirectory from _mailboxes!
 
-_mailbox_cache=(\! \< \> $muttboxes $mboxes $maildirboxes $MHboxes)
+  local i j muttrc="${muttrc:-~/.muttrc}"
+  local -aU dirboxes
+  typeset -aU -g _mailbox_cache
+  typeset -aU -g _maildir_cache _mbox_cache _mh_cache _mutt_cache _pine_cache
 
-fi
+  setopt localoptions nullglob
 
-_description expl 'mailbox specification'
-compadd "$@" "$expl[@]" - "$_mailbox_cache[@]"
+
+  [[ -f ${~muttrc:-.} ]] &&
+    _mutt_cache=( ${$(grep mailboxes ${~muttrc})[2,-1]} )
+
+  _mbox_cache=( ${~maildirectory}/*(^/) )
+  _pine_cache=( ${~pinedirectory}/**/*(.) )
+
+  dirboxes=( ${~maildirectory}/*(/) )
+
+  while (( $#dirboxes )); do
+    i=${dirboxes[1]}
+    shift dirboxes
+    if [[ -d "$i/cur" ]]; then
+      _maildir_cache=( "${_maildir_cache[@]}" "$i" )
+    elif j=( "$i"/<1-> ) && [[ -n "$j" ]]; then
+      _mh_cache=( "${_mh_cache[@]}" "$i" )
+    else
+      _mbox_cache=( "${_mbox_cache[@]}" "$i"/*(.) )
+      dirboxes=( $dirboxes "$i"/*(/) )
+    fi
+  done
+
+  [[ -n "$mailpath" ]] &&
+      _mailbox_cache=( "${_mailbox_cache[@]}" "${(@)mailpath%%\?*}" )
+
+  [[ -n "$MAIL" ]] && _mailbox_cache=( "${_mailbox_cache[@]}" $MAIL )
+}
+
+_mua_mailboxes() {
+  # Depends on $maildirectory and $pinedirectory from _mailboxes!
+
+  local -a mbox_short
+  local -aU mbox_names
+  local ret=1
+
+  case "${curcontext}" in
+    (*:elm:*) # I've probably got this wrong, or at least incomplete
+      mbox_names=( "${_mbox_cache[@]}" "${_mailbox_cache[@]}" )
+      mbox_short=( \! \< \> )
+      ;;
+    (*:mail:*)
+      if compset -P +; then
+        mbox_names=( "${(@)_mbox_cache#$~maildirectory/}" )
+      else
+        mbox_names=( +"${(@)^_mbox_cache#$~maildirectory/}"
+		    "${_mailbox_cache[@]}" )
+      fi
+      ;;
+    (*:mh:*) # I've probably got this wrong, or at least incomplete
+      (( $#_mh_cache )) && _multi_parts "${expl[@]}" / _mh_cache && ret=0
+      ;;
+    (*:mush:*)
+      if compset -P %; then
+        mbox_short=( "${(@k)userdirs}" )
+      elif compset -P +; then
+        mbox_names=( "${(@)_mbox_cache#$~maildirectory/}" )
+      else
+        mbox_names=( +"${(@)^_mbox_cache#$~maildirectory/}"
+		     "${_mailbox_cache[@]}" )
+        mbox_short=( \& % %"${(@k)^userdirs}" )
+      fi
+      ;;
+    (*:mutt:*)
+      mbox_names=( "${_mutt_cache[@]}" "${_mailbox_cache[@]}"
+		   "${_maildir_cache[@]}" )
+      mbox_short=( \! \< \> );;
+    (*:pine:*)
+      # Pine is like mail but with no leading `+' to disambiguate;
+      # any files not in $pinedirectory must be absolute paths.
+      mbox_names=( "${(@)_pine_cache#$~pinedirectory/}" "${_mbox_cache[@]}"
+		   "${_mailbox_cache[@]}" "${_mh_cache[@]}" )
+      ;;
+    (*:tkrat:*) # Has a couple of custom formats I haven't programmed for.
+      mbox_names=( "${_mbox_cache[@]}"
+		   "${_mailbox_cache[@]}" "${_mh_cache[@]}" )
+      ;;
+    (*:(zmail|zmlite):*)
+      if compset -P %; then
+        mbox_short=( "${(@k)userdirs}" )
+      elif compset -P +; then
+        mbox_names=( "${(@)_mbox_cache#$~maildirectory/}" )
+      else
+        mbox_names=( +"${(@)^_mbox_cache#$~maildirectory/}"
+		     "${_mailbox_cache[@]}" "${_mh_cache[@]}" )
+        mbox_short=( \& % %"${(@k)^userdirs}" )
+      fi
+      ;;
+    (*) # Some other program wants mailbox names?  Use them all?
+       mbox_names=( "${_mailbox_cache[@]}" "${_mbox_cache[@]}"
+		    "${_mh_cache[@]}" "${_mutt_cache[@]}" "${_pine_cache[@]}" )
+       ;;
+  esac
+
+  (( $#mbox_names )) && _multi_parts "$@" / mbox_names && ret=0
+  (( $#mbox_short )) && compadd "$@" -a mbox_short && ret=0
+  return ret
+}
+
+[[ -o kshautoload ]] || _mailboxes "$@"