1 #compdef notmuch -p notmuch-*
3 # ZSH completion for `notmuch`
4 # Copyright © 2018 Vincent Breitmoser <look@my.amazin.horse>
7 local -a notmuch_commands
9 'help:display documentation for a subcommand'
10 'setup:interactively configure notmuch'
12 'address:output addresses from matching messages'
13 'compact:compact the notmuch database'
14 'config:access notmuch configuration file'
15 'count:count messages matching the given search terms'
16 'dump:creates a plain-text dump of the tags of each message'
17 'insert:add a message to the maildir and notmuch database'
18 'new:incorporate new mail into the notmuch database'
19 'reindex:re-index a set of messages'
20 'reply:constructs a reply template for a set of messages'
21 'restore:restores the tags from the given file (see notmuch dump)'
22 'search:search for messages matching the given search terms'
23 'show:show messages matching the given search terms'
24 'tag:add/remove tags for all messages matching the search terms'
27 if ((CURRENT == 1)); then
28 _describe -t commands 'notmuch command' notmuch_commands
30 local curcontext="$curcontext"
32 if (( $+functions[_notmuch_$cmd] )); then
35 _message -e "unknown command $cmd"
40 _notmuch_term_tag _notmuch_term_is () {
44 notmuch_tags=( ${(f)"$(notmuch search --output=tags '*')"} )
46 _description notmuch-tag expl 'tag'
47 compadd "$expl[@]" -a notmuch_tags && ret=0
51 _notmuch_term_to _notmuch_term_from() {
55 _notmuch_term_mimetype() {
63 _description typical-mimetypes expl 'common types'
64 compadd "$expl[@]" -a commontypes && ret=0
70 _notmuch_term_path() {
72 local maildir="$(notmuch config get database.mail_root)"
73 [[ -d $maildir ]] || { _message -e "database.mail_root not found" ; return $ret }
75 _description notmuch-folder expl 'maildir folder'
76 _files "$expl[@]" -W $maildir -/ && ret=0
80 _notmuch_term_folder() {
82 local maildir="$(notmuch config get database.mail_root)"
83 [[ -d $maildir ]] || { _message -e "database.mail_root not found" ; return $ret }
85 _description notmuch-folder expl 'maildir folder'
86 local ignoredfolders=( '*/(cur|new|tmp)' )
87 _files "$expl[@]" -W $maildir -F ignoredfolders -/ && ret=0
91 _notmuch_term_query() {
94 local -a query_names query_content
95 for line in ${(f)"$(notmuch config list | grep '^query.')"}; do
96 query_name=${${line%%=*}#query.}
97 query_names+=( $query_name )
98 query_content+=( "$query_name = ${line#*=}" )
101 _description notmuch-named-query expl 'named query'
102 compadd "$expl[@]" -d query_content -a query_names && ret=0
106 _notmuch_search_term() {
107 local ret=1 expl match
108 setopt localoptions extendedglob
110 typeset -a notmuch_search_terms
111 notmuch_search_terms=(
112 'from' 'to' 'subject' 'attachment' 'mimetype' 'tag' 'id' 'thread' 'path' 'folder' 'date' 'lastmod' 'query' 'property'
115 if compset -P '(#b)([^:]#):'; then
116 if (( $+functions[_notmuch_term_$match[1]] )); then
117 _notmuch_term_$match[1] && ret=0
119 elif (( $+notmuch_search_terms[(r)$match[1]] )); then
120 _message "search term '$match[1]'" && ret=0
123 _message -e "unknown search term '$match[1]'"
128 _description notmuch-term expl 'search term'
129 compadd "$expl[@]" -S ':' -a notmuch_search_terms && ret=0
131 if [[ $CURRENT -gt 1 && $words[CURRENT-1] != '--' ]]; then
132 _description notmuch-op expl 'boolean operator'
133 compadd "$expl[@]" -- and or not xor && ret=0
139 _notmuch_tagging_or_search() {
140 setopt localoptions extendedglob
142 local -a notmuch_tags
144 # first arg that is a search term, or $#words+1
145 integer searchtermarg=$(( $words[(I)--] != 0 ? $words[(i)--] : $words[(i)^(-|+)*] ))
147 if (( CURRENT > 1 )); then
149 local -a words=( $argv )
150 local CURRENT=$(( CURRENT - searchtermarg + 1 ))
151 _notmuch_search_term && ret=0
152 } $words[searchtermarg,$]
155 # only complete +/- tags if we're before the first search term
156 if (( searchtermarg >= CURRENT )); then
157 if compset -P '+'; then
158 notmuch_tags=( ${(f)"$(notmuch search --output=tags '*')"} )
159 _description notmuch-tag expl 'add tag'
160 compadd "$expl[@]" -a notmuch_tags
162 elif compset -P '-'; then
163 notmuch_tags=( ${(f)"$(notmuch search --output=tags '*')"} )
164 _description notmuch-tag expl 'remove tag'
165 compadd "$expl[@]" -a notmuch_tags
168 _description notmuch-tag expl 'add or remove tags'
169 compadd "$expl[@]" -S '' -- '+' '-' && ret=0
178 '--format=[set output format]:output format:(json sexp text text0)' \
179 '--format-version=[set output format version]:format version: ' \
180 '--sort=[sort results]:sorting:((newest-first\:"reverse chronological order" oldest-first\:"chronological order"))' \
181 '--output=[select output format]:output format:(sender recipients count address)' \
182 '--deduplicate=[deduplicate results]:deduplication mode:(no mailbox address)' \
183 '--exclude=[respect excluded tags setting]:exclude tags:(true false)' \
184 '*::search term:_notmuch_search_term'
189 '--backup=[save a backup before compacting]:backup directory:_files -/' \
190 '--quiet[do not print progress or results]'
196 '--lastmod[append lastmod and uuid to output]' \
197 '--exclude=[respect excluded tags setting]:exclude tags:(true false)' \
198 '--output=[select what to count]:output format:(messages threads files)' \
199 '*::search term:_notmuch_search_term' \
201 '--batch[operate in batch mode]' \
202 '(--batch)--input=[read batch operations from file]:batch file:_files'
207 '--gzip[compress output with gzip]' \
208 '--format=[specify output format]:output format:(batch-tag sup)' \
209 '*--include=[configure metadata to output (default all)]:metadata type:(config properties tags)' \
210 '--output=[write output to file]:output file:_files' \
211 '*::search term:_notmuch_search_term'
216 '--no-hooks[prevent hooks from being run]' \
217 '--quiet[do not print progress or results]' \
218 '--full-scan[don''t rely on directory modification times for scan]' \
219 '--decrypt=[decrypt messages]:decryption setting:((false\:"never decrypt" auto\:"decrypt if session key is known (default)" true\:"decrypt using secret keys" stash\:"decrypt, and store session keys"))'
224 '--decrypt=[decrypt messages]:decryption setting:((false\:"never decrypt" auto\:"decrypt if session key is known (default)" true\:"decrypt using secret keys" stash\:"decrypt, and store session keys"))' \
225 '*::search term:_notmuch_search_term'
230 '--max-threads=[display only the first x threads from the search results]:number of threads to show: ' \
231 '--first=[omit the first x threads from the search results]:number of threads to omit: ' \
232 '--sort=[sort results]:sorting:((newest-first\:"reverse chronological order" oldest-first\:"chronological order"))' \
233 '--output=[select what to output]:output:(summary threads messages files tags)' \
234 '*::search term:_notmuch_search_term'
239 '--entire-thread=[output entire threads]:show thread:(true false)' \
240 '--format=[set output format]:output format:(text json sexp mbox raw)' \
241 '--format-version=[set output format version]:format version: ' \
242 '--part=[output a single decoded mime part]:part number: ' \
243 '--verify[verify signed MIME parts]' \
244 '--decrypt=[decrypt messages]:decryption setting:((false\:"never decrypt" auto\:"decrypt if session key is known (default)" true\:"decrypt using secret keys" stash\:"decrypt, and store session keys"))' \
245 '--exclude=[respect excluded tags setting]:exclude tags:(true false)' \
246 '--body=[output body]:output body content:(true false)' \
247 '--include-html[include text/html parts in the output]' \
248 '--limit=[limit the number of displayed results]:limit: ' \
249 '--offset=[skip displaying the first N results]:offset: ' \
250 '*::search term:_notmuch_search_term'
255 '--format=[set output format]:output format:(default json sexp headers-only)' \
256 '--format-version=[set output format version]:output format version: ' \
257 '--reply-to=[specify recipient types]:recipient types:(all sender)' \
258 '--decrypt=[decrypt messages]:decryption setting:((false\:"never decrypt" auto\:"decrypt if session key is known (default)" true\:"decrypt using secret keys"))' \
259 '*::search term:_notmuch_search_term'
264 '--acumulate[add data to db instead of replacing]' \
265 '--format=[specify input format]:input format:(auto batch-tag sup)' \
266 '*--include=[configure metadata to import (default all)]:metadata type:(config properties tags)' \
267 '--input=[read from file]:notmuch dump file:_files'
273 '--remove-all[remove all tags from matching messages]:*:search term:_notmuch_search_term' \
274 '*::tag or search:_notmuch_tagging_or_search' \
276 '--batch[operate in batch mode]' \
277 '(--batch)--input=[read batch operations from file]:batch file:_files'
281 if [[ $service == notmuch-* ]]; then
282 local compfunc=_${service//-/_}
283 (( $+functions[$compfunc] )) || return 1
287 '(* -)--help[show help]' \
288 '(* -)--version[show version]' \
289 '--config=-[specify config file]:config file:_files' \
290 '--uuid=-[check against database uuid or exit]:uuid: ' \
291 '*::notmuch commands:_notmuch_command'