zsh-workers
 help / color / mirror / code / Atom feed
8a5877a9ca22d8ea5210e1d58f22c2a294101c9c blob 5628 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
 
#autoload
# options:
#
# -n plugin - can complete nicknames from specified plugin
# -s sep    - complete a list of addresses separated by specified character
# -c        - e-mail address must be of form user@host (no comments or aliases)
#
# TODO: with -n, have the named plugin complete not only aliases but also addresses?
# 
# Plugins are written as separate functions with names starting `_email-'.
# They should either do their own completion or return the addresses in the
# reply array in the form 'alias:address' and return 300. The -c option is
# passed on to plugins (and -n could be if needed ever). New plugins will be
# picked up and run automatically.

# plugins
(( $+functions[_email-mail] )) ||
_email-mail() {
  local rc rcfiles i

  rcfiles=( $files[$plugin] )
  for ((i=1;i<=$#rcfiles;i++)); do
    rcfiles+=( ${~${(M)${(f)"$(<$rcfiles[i])"}:#source*}##source[[:blank:]]##}(N) )
  done
  reply=()
  for rc in $rcfiles; do
    reply+=( ${${${(M)${(f)"$(<$rc)"}:#alias*}##alias[[:blank:]]##}/[[:blank:]]##/:} )
  done
  return 300
}
(( $+functions[_email-mutt] )) || _email-mutt() { _email-mail }
(( $+functions[_email-mush] )) || _email-mush() { _email-mail }

(( $+functions[_email-MH] )) ||
_email-MH() {
  reply=( ${${(f)"$(_call_program aliases ali 2>/dev/null)"}/: /:} )
  return 300
}

(( $+functions[_email-pine] )) ||
_email-pine() {
  reply=( ${${${${${(f)"$(<~/.addressbook)"}:#*DELETED*}:#\ *}/	[^	]#	/:}%%	*} )
  return 300
}

(( $+functions[_email-ldap] )) ||
_email-ldap() {
  local -a expl ali res filter
  local -A opts
  local dn cn mail
  
  zparseopts -D -E -A opts c

  zstyle -a ":completion:${curcontext}:$curtag" filter filter
  (( $#filter )) || return
  
  filter=( "("${filter}"=${PREFIX}*${SUFFIX})" )
  (( $#filter > 1 )) && filter="(|"${(j..)filter}")"
  res=( ${(f)"$(_call_program $curtag ldapsearch -LLL \$filter cn mail 2>/dev/null)"} )
  (( $#res > 1 )) || return

  for dn cn mail in "${res[@]}"; do
    if (( $+opts[-c] )); then
      ali+=( "${mail#*: }" )
    else
      cn="${cn#*: }"
      [[ $cn = *$~__specials* ]] && cn="\"$cn\""
      ali+=( "$cn <${mail#*: }>" )
    fi
  done
  compstate[insert]=menu
  _wanted email-ldap expl 'matching names' \
      compadd -U -i "$IPREFIX" -I "$ISUFFIX" "$@" -a - ali
}

(( $+functions[_email-local] )) ||
_email-local() {
  local suf opts
  zparseopts -D -E -A opts c S:=suf

  if compset -P '*@'; then
    _hosts "$@" "$suf[@]"
  else
    suf=()
    compset -S '@*' || suf=( -qS @ )
    _users "$suf[@]" "$@"
  fi
}

_email_addresses() {
  local -a plugins reply list args
  local -A opts files
  local plugin rcfile muttrc expl sep ret fret

  local __specialx='][()<>@,;:\\".'
  local __spacex=" 	"				# Space, tab
  local __specials="[$__specialx]"
  local __atom="[^$__specialx$__spacex]##"
  local __space="[$__spacex]#"				# Really, space or comment
  local __qtext='[^"\\]'
  local __qpair='\\?'
  local __beginq='"'
  local __endq='(|[^\\])"'
  local __dot="$__space.$__space"

  local __domainref="$__atom"
  local __domainlit='\[([^]]|'"$__qpair"')#(|[^\\])\]'
  local __quotedstring="$__beginq($__qtext|$__qpair)#$__endq"
  local __word="($__atom|$__quotedstring)"
  local __phrase="($__space$__word$__space)#"		# Strictly, should use `##'
  local __localpart="$__word($__dot$__word)#"

  local __subdomain="($__domainref|$__domainlit)"
  local __domain="$__subdomain($__dot$__subdomain)#"
  local __addrspec="$__localpart$__space@$__space$__domain"

  local __addresses="($__qtext|$__quotedstring)##"

  zparseopts -D -E -A opts n: s: c
  set -- "$@" -M 'r:|[.@]=* r:|=* m:{a-zA-Z}={A-Za-z}'

  if [[ -n $opts[-s] ]]; then
    # remove up to the last unquoted separator
    if [[ ${(Q)PREFIX} = (#b)($~__addresses$opts[-s])* ]]; then
      IFS="$opts[-s]" eval 'compset -P $(( ${#${=${:-x${match[1]}x}}} - 1 )) "*${opts[-s]}"'
    fi

    # for the suffix, I'm too lazy to work out how to preserve quoted separators
    compset -S "$opts[-s]*" || set -- -q -S "$opts[-s]" "$@"
  fi

  # get list of all plugins except any with missing config files
  if ! zstyle -s ":completion:${curcontext}:email-addresses" muttrc muttrc; then
    [[ -e ~/mutt/muttrc ]] && muttrc="~/mutt/muttrc" || muttrc="~/.muttrc"
  fi
  files=( MH ${MH:-~/.mh_profile} mutt $~muttrc mush ~/.mushrc mail ${MAILRC:-~/.mailrc} pine ~/.addressbook )
  plugins=( 
    ${${(k)functions[(I)_email-*]#*-}:#(${(kj.|.)~files})}
    $files(Ne:'REPLY=( ${(k)files[(r)$REPLY]} ):')
  )

  ret=1
  _tags email-$plugins
  while _tags; do
    for plugin in $plugins; do
      if _requested email-$plugin; then
	while _next_label email-$plugin expl 'email address'; do

          args=()
	  if (( $+opts[-c] )) || zstyle -t \
	      ":completion:${curcontext}:$curtag" strip-comments
	  then
	    args=( '-c' )
	  fi
	  
	  if ! _call_function fret _email-$plugin "$@" $args; then
	    _message "$plugin: plugin not found"
	    continue
	  fi
	  ret=$(( ret && fret ))

	  if (( fret == 300 )); then
	    if (( ! $+opts[-c] )) && [[ $opts[-n] = $plugin ]]; then
	      zstyle -s ":completion:${curcontext}:$curtag" list-separator sep || sep=--
	      zformat -a list " $sep " "${reply[@]}"
	      _wanted mail-aliases expl 'alias' compadd "$@" \
		  -d list - ${reply%%:*} && ret=0
	    else
	      if (( $#args )); then
		reply=( ${(SM)${reply#*:}##$~__addrspec} )
	      else
		# remove lines not containing `@' as they probably aren't addresses
		reply=( "${(@)${(M@)reply:#*@*}#*:}" )
	      fi
	      compadd -a "$@" "$expl[@]" reply && ret=0
	    fi
	  fi
	done
      fi
    done
    (( ret )) || return 0
  done

  return 1
}

_email_addresses "$@"
debug log:

solving 8a5877a9c ...
found 8a5877a9c in https://git.vuxu.org/mirror/zsh/

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).