[PATCH (draft)] company model for external programs
Mark Walters
markwalters1009 at gmail.com
Tue Oct 27 02:05:28 PDT 2015
---
This is an attempt to make company mode work for external address
completion programs. We need to be able to run the address completion
asynchronously.
The changes are three fold: separate out the internal completion code
into its own function, allow the external program to be called
asynchronously, and copy the relevant code from the emacs function
process-lines into our function as it doesn't appear to be available
as a separate function.
It seems to work in light testing but asynchronous emacs is always a
little fragile/tricky.
Best wishes
Mark
emacs/notmuch-address.el | 2 +-
emacs/notmuch-company.el | 65 +++++++++++++++++++++++++++++++++++++-----------
2 files changed, 51 insertions(+), 16 deletions(-)
diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el
index 49e2402..65d04ce 100644
--- a/emacs/notmuch-address.el
+++ b/emacs/notmuch-address.el
@@ -81,7 +81,7 @@ (defcustom notmuch-address-use-company t
(defun notmuch-address-setup ()
(let* ((use-company (and notmuch-address-use-company
- (eq notmuch-address-command 'internal)
+ ;; (eq notmuch-address-command 'internal)
(require 'company nil t)))
(pair (cons notmuch-address-completion-headers-regexp
(if use-company
diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el
index add3161..dc3d018 100644
--- a/emacs/notmuch-company.el
+++ b/emacs/notmuch-company.el
@@ -42,6 +42,7 @@ (defvar company-backends)
(declare-function notmuch-address-matching "notmuch-address")
(defvar notmuch-address-full-harvest-finished)
(defvar notmuch-address-completion-headers-regexp)
+(defvar notmuch-address-command)
;;;###autoload
(defun notmuch-company-setup ()
@@ -49,6 +50,54 @@ (defun notmuch-company-setup ()
(make-local-variable 'company-backends)
(setq company-backends '(notmuch-company)))
+(defun notmuch-company-address-internal (arg)
+ (cond
+ (notmuch-address-full-harvest-finished
+ ;; Update harvested addressed from time to time
+ (notmuch-address-harvest-trigger)
+ (notmuch-address-matching arg))
+ (t
+ (cons :async
+ (lambda (callback)
+ ;; First run quick asynchronous harvest based on what the user entered so far
+ (notmuch-address-harvest
+ (format "to:%s*" arg) nil
+ (lambda (_proc _event)
+ (funcall callback (notmuch-address-matching arg))
+ ;; Then start the (potentially long-running) full asynchronous harvest if necessary
+ (notmuch-address-harvest-trigger))))))))
+
+(defun notmuch-company-external-sentinel (callback proc _event)
+ (let (lines)
+ (with-current-buffer (process-buffer proc)
+ ;; Copied verbatim from the process-lines function in subr.el in
+ ;; the standard emacs distribution.
+ (goto-char (point-min))
+ (while (not (eobp))
+ (setq lines (cons (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))
+ lines))
+ (forward-line 1))
+ (message "lines %s" lines))
+ (kill-buffer (process-buffer proc))
+ (funcall callback (nreverse lines))))
+
+(defun notmuch-company-address-external (arg)
+ (cons :async
+ (lambda (callback)
+ (let* ((buf (generate-new-buffer " *notmuch-external-address*"))
+ (proc (start-process "notmuch-external-address" buf
+ notmuch-address-command arg)))
+ (set-process-sentinel proc (apply-partially
+ 'notmuch-company-external-sentinel
+ callback))))))
+
+(defun notmuch-company-address (arg)
+ (if (eq notmuch-address-command 'internal)
+ (notmuch-company-address-internal arg)
+ (notmuch-company-address-external arg)))
+
;;;###autoload
(defun notmuch-company (command &optional arg &rest _ignore)
"`company-mode' completion back-end for `notmuch'."
@@ -62,21 +111,7 @@ (defun notmuch-company (command &optional arg &rest _ignore)
(looking-back (concat notmuch-address-completion-headers-regexp ".*")
(line-beginning-position))
(setq notmuch-company-last-prefix (company-grab "[:,][ \t]*\\(.*\\)" 1 (point-at-bol)))))
- (candidates (cond
- (notmuch-address-full-harvest-finished
- ;; Update harvested addressed from time to time
- (notmuch-address-harvest-trigger)
- (notmuch-address-matching arg))
- (t
- (cons :async
- (lambda (callback)
- ;; First run quick asynchronous harvest based on what the user entered so far
- (notmuch-address-harvest
- (format "to:%s*" arg) nil
- (lambda (_proc _event)
- (funcall callback (notmuch-address-matching arg))
- ;; Then start the (potentially long-running) full asynchronous harvest if necessary
- (notmuch-address-harvest-trigger))))))))
+ (candidates (notmuch-company-address arg))
(match (if (string-match notmuch-company-last-prefix arg)
(match-end 0)
0))
--
2.1.4
More information about the notmuch
mailing list