]> rtime.felk.cvut.cz Git - notmuch.git/blob - emacs/notmuch-company.el
Emacs: Add address completion based on company-mode
[notmuch.git] / emacs / notmuch-company.el
1 ;; notmuch-company.el --- Mail address completion for notmuch via company-mode  -*- no-byte-compile: t; lexical-binding: t -*-
2
3
4 ;; Authors: Trevor Jim <tjim@mac.com>
5 ;;          Michal Sojka <sojkam1@fel.cvut.cz>
6 ;;
7 ;; Keywords: mail, completion
8
9 ;; This program is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
13
14 ;; This program is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 ;;; Commentary:
23
24 ;; To enable this, install company mode (https://company-mode.github.io/)
25 ;; and add
26 ;;
27 ;;     (require 'notmuch-company)
28 ;;
29 ;; to your .emacs.
30 ;;
31 ;; NB company-minimum-prefix-length defaults to 3 so you don't get
32 ;; completion unless you type 3 characters
33
34 ;;; Code:
35
36 (require 'company)
37 (require 'message)
38 (require 'notmuch-address)
39 (require 'cl-lib)
40
41 (defvar-local notmuch-company-last-prefix nil)
42
43 ;;;###autoload
44 (defun notmuch-company (command &optional arg &rest ignore)
45   "`company-mode' completion back-end for `notmuch'."
46   (interactive (list 'interactive))
47   (let ((case-fold-search t)
48         (completion-ignore-case t))
49     (cl-case command
50       (interactive (company-begin-backend 'notmuch-company))
51       (prefix (and (eq major-mode 'message-mode)
52                    (looking-back "^\\(To\\|Cc\\|Bcc\\):.*"
53                                  (line-beginning-position))
54                    (setq notmuch-company-last-prefix (company-grab "[:,][ \t]*\\(.*\\)" 1 (point-at-bol)))))
55       (candidates (cond
56                    (notmuch-address-full-harvest-finished
57                     ;; Update harvested addressed from time to time
58                     (notmuch-address-harvest-trigger)
59                     (notmuch-address-matching arg))
60                    (t
61                     (cons :async
62                           (lambda (callback)
63                             ;; First run quick asynchronous harvest based on what the user entered so far
64                             (notmuch-address-harvest
65                              (format "to:%s*" arg) nil
66                              (lambda (proc event)
67                                (funcall callback (notmuch-address-matching arg))
68                                ;; Then (re)start potentially long-running full asynchronous harvesting
69                                (notmuch-address-harvest-trigger))))))))
70       (match (if (string-match notmuch-company-last-prefix arg)
71                  (match-end 0)
72                0))
73       (no-cache t))))
74
75 ;;;###autoload
76 (add-hook 'message-mode-hook '(lambda ()
77                                 (company-mode)
78                                 (make-local-variable 'company-backends)
79                                 (setq company-backends '(notmuch-company))))
80
81 (provide 'notmuch-company)