]> git.notmuchmail.org Git - notmuch/blob - completion/notmuch-completion.bash
Merge tag '0.23.5'
[notmuch] / completion / notmuch-completion.bash
1 # bash completion for notmuch                              -*- shell-script -*-
2 #
3 # Copyright © 2013 Jani Nikula
4 #
5 # Based on the bash-completion package:
6 # https://github.com/scop/bash-completion
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 2 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program.  If not, see https://www.gnu.org/licenses/ .
20 #
21 # Author: Jani Nikula <jani@nikula.org>
22 #
23 #
24 # BUGS:
25 #
26 # Add space after an --option without parameter (e.g. reply --decrypt)
27 # on completion.
28 #
29
30 _notmuch_shared_options="--help --uuid= --version"
31
32 # $1: current input of the form prefix:partialinput, where prefix is
33 # to or from.
34 _notmuch_email()
35 {
36     local output prefix cur
37
38     prefix="${1%%:*}"
39     cur="${1#*:}"
40
41     # Cut the input to be completed at punctuation because
42     # (apparently) Xapian does not support the trailing wildcard '*'
43     # operator for input with punctuation. We let compgen handle the
44     # extra filtering required.
45     cur="${cur%%[^a-zA-Z0-9]*}"
46
47     case "$prefix" in
48         # Note: It would be more accurate and less surprising to have
49         # output=recipients here for to: addresses, but as gathering
50         # the recipient addresses requires disk access for each
51         # matching message, this becomes prohibitively slow.
52         to|from) output=sender;;
53         *) return;;
54     esac
55
56     # Only emit plain, lower case, unique addresses.
57     notmuch address --output=$output $prefix:"${cur}*" | \
58         sed 's/[^<]*<\([^>]*\)>/\1/' | tr "[:upper:]" "[:lower:]" | sort -u
59 }
60
61 _notmuch_mimetype()
62 {
63     # use mime types from mime-support package if available, and fall
64     # back to a handful of common ones otherwise
65     if [ -r "/etc/mime.types" ]; then
66         sed -n '/^[[:alpha:]]/{s/[[:space:]].*//;p;}' /etc/mime.types
67     else
68         cat <<EOF
69 application/gzip
70 application/msword
71 application/pdf
72 application/zip
73 audio/mpeg
74 audio/ogg
75 image/gif
76 image/jpeg
77 image/png
78 message/rfc822
79 text/calendar
80 text/html
81 text/plain
82 text/vcard
83 text/x-diff
84 text/x-vcalendar
85 EOF
86     fi
87 }
88
89 _notmuch_search_terms()
90 {
91     local cur prev words cword split
92     # handle search prefixes and tags with colons and equal signs
93     _init_completion -n := || return
94
95     case "${cur}" in
96         tag:*)
97             COMPREPLY=( $(compgen -P "tag:" -W "`notmuch search --output=tags \*`" -- ${cur##tag:}) )
98             ;;
99         to:*)
100             COMPREPLY=( $(compgen -P "to:" -W "`_notmuch_email ${cur}`" -- ${cur##to:}) )
101             ;;
102         from:*)
103             COMPREPLY=( $(compgen -P "from:" -W "`_notmuch_email ${cur}`" -- ${cur##from:}) )
104             ;;
105         path:*)
106             local path=`notmuch config get database.path`
107             compopt -o nospace
108             COMPREPLY=( $(compgen -d "$path/${cur##path:}" | sed "s|^$path/||" ) )
109             ;;
110         folder:*)
111             local path=`notmuch config get database.path`
112             compopt -o nospace
113             COMPREPLY=( $(compgen -d "$path/${cur##folder:}" | \
114                 sed "s|^$path/||" | grep -v "\(^\|/\)\(cur\|new\|tmp\)$" ) )
115             ;;
116         mimetype:*)
117             compopt -o nospace
118             COMPREPLY=( $(compgen -P "mimetype:" -W "`_notmuch_mimetype ${cur}`" -- ${cur##mimetype:}) )
119             ;;
120         *)
121             local search_terms="from: to: subject: attachment: mimetype: tag: id: thread: folder: path: date: lastmod:"
122             compopt -o nospace
123             COMPREPLY=( $(compgen -W "${search_terms}" -- ${cur}) )
124             ;;
125     esac
126     # handle search prefixes and tags with colons
127     __ltrim_colon_completions "${cur}"
128 }
129
130 _notmuch_compact()
131 {
132     local cur prev words cword split
133     _init_completion -s || return
134
135     $split &&
136     case "${prev}" in
137         --backup)
138             _filedir -d
139             return
140             ;;
141     esac
142
143     ! $split &&
144     case "${cur}" in
145         -*)
146             local options="--backup= --quiet ${_notmuch_shared_options}"
147             compopt -o nospace
148             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
149             ;;
150     esac
151 }
152
153 _notmuch_config()
154 {
155     local cur prev words cword split
156     _init_completion || return
157
158     case "${prev}" in
159         config)
160             COMPREPLY=( $(compgen -W "get set list" -- ${cur}) )
161             ;;
162         get|set)
163             COMPREPLY=( $(compgen -W "`notmuch config list | sed 's/=.*\$//'`" -- ${cur}) )
164             ;;
165         # these will also complete on config get, but we don't care
166         database.path)
167             _filedir -d
168             ;;
169         maildir.synchronize_flags)
170             COMPREPLY=( $(compgen -W "true false" -- ${cur}) )
171             ;;
172     esac
173 }
174
175 _notmuch_count()
176 {
177     local cur prev words cword split
178     _init_completion -s || return
179
180     $split &&
181     case "${prev}" in
182         --output)
183             COMPREPLY=( $( compgen -W "messages threads files" -- "${cur}" ) )
184             return
185             ;;
186         --exclude)
187             COMPREPLY=( $( compgen -W "true false" -- "${cur}" ) )
188             return
189             ;;
190         --input)
191             _filedir
192             return
193             ;;
194     esac
195
196     ! $split &&
197     case "${cur}" in
198         -*)
199             local options="--output= --exclude= --batch --input= --lastmod ${_notmuch_shared_options}"
200             compopt -o nospace
201             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
202             ;;
203         *)
204             _notmuch_search_terms
205             ;;
206     esac
207 }
208
209 _notmuch_dump()
210 {
211     local cur prev words cword split
212     _init_completion -s || return
213
214     $split &&
215     case "${prev}" in
216         --format)
217             COMPREPLY=( $( compgen -W "sup batch-tag" -- "${cur}" ) )
218             return
219             ;;
220         --output)
221             _filedir
222             return
223             ;;
224     esac
225
226     ! $split &&
227     case "${cur}" in
228         -*)
229             local options="--gzip --format= --output= ${_notmuch_shared_options}"
230             compopt -o nospace
231             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
232             ;;
233         *)
234             _notmuch_search_terms
235             ;;
236     esac
237 }
238
239 _notmuch_insert()
240 {
241     local cur prev words cword split
242     # handle tags with colons and equal signs
243     _init_completion -s -n := || return
244
245     $split &&
246     case "${prev}" in
247         --folder)
248             local path=`notmuch config get database.path`
249             compopt -o nospace
250             COMPREPLY=( $(compgen -d "$path/${cur}" | \
251                 sed "s|^$path/||" | grep -v "\(^\|/\)\(cur\|new\|tmp\)$" ) )
252             return
253             ;;
254     esac
255
256     ! $split &&
257     case "${cur}" in
258         --*)
259             local options="--create-folder --folder= --keep --no-hooks ${_notmuch_shared_options}"
260             compopt -o nospace
261             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
262             return
263             ;;
264         +*)
265             COMPREPLY=( $(compgen -P "+" -W "`notmuch search --output=tags \*`" -- ${cur##+}) )
266             ;;
267         -*)
268             COMPREPLY=( $(compgen -P "-" -W "`notmuch search --output=tags \*`" -- ${cur##-}) )
269             ;;
270     esac
271     # handle tags with colons
272     __ltrim_colon_completions "${cur}"
273 }
274
275 _notmuch_new()
276 {
277     local cur prev words cword split
278     _init_completion || return
279
280     case "${cur}" in
281         -*)
282             local options="--no-hooks --quiet ${_notmuch_shared_options}"
283             compopt -o nospace
284             COMPREPLY=( $(compgen -W "${options}" -- ${cur}) )
285             ;;
286     esac
287 }
288
289 _notmuch_reply()
290 {
291     local cur prev words cword split
292     _init_completion -s || return
293
294     $split &&
295     case "${prev}" in
296         --format)
297             COMPREPLY=( $( compgen -W "default json sexp headers-only" -- "${cur}" ) )
298             return
299             ;;
300         --reply-to)
301             COMPREPLY=( $( compgen -W "all sender" -- "${cur}" ) )
302             return
303             ;;
304     esac
305
306     ! $split &&
307     case "${cur}" in
308         -*)
309             local options="--format= --format-version= --reply-to= --decrypt ${_notmuch_shared_options}"
310             compopt -o nospace
311             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
312             ;;
313         *)
314             _notmuch_search_terms
315             ;;
316     esac
317 }
318
319 _notmuch_restore()
320 {
321     local cur prev words cword split
322     _init_completion -s || return
323
324     $split &&
325     case "${prev}" in
326         --format)
327             COMPREPLY=( $( compgen -W "sup batch-tag auto" -- "${cur}" ) )
328             return
329             ;;
330         --input)
331             _filedir
332             return
333             ;;
334     esac
335
336     ! $split &&
337     case "${cur}" in
338         -*)
339             local options="--format= --accumulate --input= ${_notmuch_shared_options}"
340             compopt -o nospace
341             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
342             ;;
343     esac
344 }
345
346 _notmuch_search()
347 {
348     local cur prev words cword split
349     _init_completion -s || return
350
351     $split &&
352     case "${prev}" in
353         --format)
354             COMPREPLY=( $( compgen -W "json sexp text text0" -- "${cur}" ) )
355             return
356             ;;
357         --output)
358             COMPREPLY=( $( compgen -W "summary threads messages files tags" -- "${cur}" ) )
359             return
360             ;;
361         --sort)
362             COMPREPLY=( $( compgen -W "newest-first oldest-first" -- "${cur}" ) )
363             return
364             ;;
365         --exclude)
366             COMPREPLY=( $( compgen -W "true false flag all" -- "${cur}" ) )
367             return
368             ;;
369     esac
370
371     ! $split &&
372     case "${cur}" in
373         -*)
374             local options="--format= --output= --sort= --offset= --limit= --exclude= --duplicate= ${_notmuch_shared_options}"
375             compopt -o nospace
376             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
377             ;;
378         *)
379             _notmuch_search_terms
380             ;;
381     esac
382 }
383
384 _notmuch_address()
385 {
386     local cur prev words cword split
387     _init_completion -s || return
388
389     $split &&
390     case "${prev}" in
391         --format)
392             COMPREPLY=( $( compgen -W "json sexp text text0" -- "${cur}" ) )
393             return
394             ;;
395         --output)
396             COMPREPLY=( $( compgen -W "sender recipients count" -- "${cur}" ) )
397             return
398             ;;
399         --sort)
400             COMPREPLY=( $( compgen -W "newest-first oldest-first" -- "${cur}" ) )
401             return
402             ;;
403         --exclude)
404             COMPREPLY=( $( compgen -W "true false flag all" -- "${cur}" ) )
405             return
406             ;;
407         --deduplicate)
408             COMPREPLY=( $( compgen -W "no mailbox address" -- "${cur}" ) )
409             return
410             ;;
411     esac
412
413     ! $split &&
414     case "${cur}" in
415         -*)
416             local options="--format= --output= --sort= --exclude= --deduplicate= ${_notmuch_shared_options}"
417             compopt -o nospace
418             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
419             ;;
420         *)
421             _notmuch_search_terms
422             ;;
423     esac
424 }
425
426 _notmuch_show()
427 {
428     local cur prev words cword split
429     _init_completion -s || return
430
431     $split &&
432     case "${prev}" in
433         --entire-thread)
434             COMPREPLY=( $( compgen -W "true false" -- "${cur}" ) )
435             return
436             ;;
437         --format)
438             COMPREPLY=( $( compgen -W "text json sexp mbox raw" -- "${cur}" ) )
439             return
440             ;;
441         --exclude|--body)
442             COMPREPLY=( $( compgen -W "true false" -- "${cur}" ) )
443             return
444             ;;
445     esac
446
447     ! $split &&
448     case "${cur}" in
449         -*)
450             local options="--entire-thread= --format= --exclude= --body= --format-version= --part= --verify --decrypt --include-html ${_notmuch_shared_options}"
451             compopt -o nospace
452             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
453             ;;
454         *)
455             _notmuch_search_terms
456             ;;
457     esac
458 }
459
460 _notmuch_tag()
461 {
462     local cur prev words cword split
463     # handle tags with colons and equal signs
464     _init_completion -s -n := || return
465
466     $split &&
467     case "${prev}" in
468         --input)
469             _filedir
470             return
471             ;;
472     esac
473
474     ! $split &&
475     case "${cur}" in
476         --*)
477             local options="--batch --input= --remove-all ${_notmuch_shared_options}"
478             compopt -o nospace
479             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
480             return
481             ;;
482         +*)
483             COMPREPLY=( $(compgen -P "+" -W "`notmuch search --output=tags \*`" -- ${cur##+}) )
484             ;;
485         -*)
486             COMPREPLY=( $(compgen -P "-" -W "`notmuch search --output=tags \*`" -- ${cur##-}) )
487             ;;
488         *)
489             _notmuch_search_terms
490             return
491             ;;
492     esac
493     # handle tags with colons
494     __ltrim_colon_completions "${cur}"
495 }
496
497 _notmuch()
498 {
499     local _notmuch_commands="compact config count dump help insert new reply restore search address setup show tag"
500     local arg cur prev words cword split
501
502     # require bash-completion with _init_completion
503     type -t _init_completion >/dev/null 2>&1 || return
504
505     _init_completion || return
506
507     COMPREPLY=()
508
509     # subcommand
510     _get_first_arg
511
512     # complete --help option like the subcommand
513     if [ -z "${arg}" -a "${prev}" = "--help" ]; then
514         arg="help"
515     fi
516
517     if [ -z "${arg}" ]; then
518         # top level completion
519         case "${cur}" in
520             -*)
521                 # XXX: handle ${_notmuch_shared_options} and --config=
522                 local options="--help --version"
523                 COMPREPLY=( $(compgen -W "${options}" -- ${cur}) )
524                 ;;
525             *)
526                 COMPREPLY=( $(compgen -W "${_notmuch_commands}" -- ${cur}) )
527                 ;;
528         esac
529     elif [ "${arg}" = "help" ]; then
530         # handle help command specially due to _notmuch_commands usage
531         local help_topics="$_notmuch_commands hooks search-terms"
532         COMPREPLY=( $(compgen -W "${help_topics}" -- ${cur}) )
533     else
534         # complete using _notmuch_subcommand if one exist
535         local completion_func="_notmuch_${arg//-/_}"
536         declare -f $completion_func >/dev/null && $completion_func
537     fi
538 } &&
539 complete -F _notmuch notmuch