[PATCH (draft)] company model for external programs
authorMark Walters <markwalters1009@gmail.com>
Tue, 27 Oct 2015 09:05:28 +0000 (09:05 +0000)
committerW. Trevor King <wking@tremily.us>
Sat, 20 Aug 2016 21:49:56 +0000 (14:49 -0700)
62/3b7e266e5ed120f8b52c891970f549cfbdd3ca [new file with mode: 0644]

diff --git a/62/3b7e266e5ed120f8b52c891970f549cfbdd3ca b/62/3b7e266e5ed120f8b52c891970f549cfbdd3ca
new file mode 100644 (file)
index 0000000..6c54658
--- /dev/null
@@ -0,0 +1,191 @@
+Return-Path: <markwalters1009@gmail.com>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 393086DE1733\r
+ for <notmuch@notmuchmail.org>; Tue, 27 Oct 2015 02:05:37 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.124\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.124 tagged_above=-999 required=5 tests=[AWL=0.446,\r
+  DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
+ FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7,\r
+ RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001]\r
+ autolearn=disabled\r
+Received: from arlo.cworth.org ([127.0.0.1])\r
+ by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id 53f91SiiWBEI for <notmuch@notmuchmail.org>;\r
+ Tue, 27 Oct 2015 02:05:35 -0700 (PDT)\r
+Received: from mail-wi0-f173.google.com (mail-wi0-f173.google.com\r
+ [209.85.212.173])\r
+ by arlo.cworth.org (Postfix) with ESMTPS id E2FCA6DE13EF\r
+ for <notmuch@notmuchmail.org>; Tue, 27 Oct 2015 02:05:34 -0700 (PDT)\r
+Received: by wicll6 with SMTP id ll6so149967543wic.1\r
+ for <notmuch@notmuchmail.org>; Tue, 27 Oct 2015 02:05:31 -0700 (PDT)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;\r
+ h=from:to:cc:subject:date:message-id;\r
+ bh=6YOP8beHAArwmZTj4i+0EcVohWzQRKcyC01X5S9uqI4=;\r
+ b=W2disYO3WsNJZoB7UPcDZw6uGWbx26LJkky8OJco3Y7irMQJmrzGZhaf1a0+7x1DFI\r
+ uQVRgkZcMCGngQoHJhUJhOIyzoVDL7p532uXeSY4hHVKp7GagPdOYtxoRhl+akB77IEH\r
+ QUr+eaNEz5kbd/5Wgw6kmpE6kIGAgS/WqgvM3JX150c4veu3uDVbbvyMUJj88iSJZAF6\r
+ E0SjUtaNwVIxhfcxidzW50cldr7fTzDANieHvvd+LQfUcP9pOlc6w378KgqXJrozE6P+\r
+ Twl1Ua30QkDIB845BQRzxjKYUOnV0QdxeXU2urNiQXwen5TAoj9zb6Gw9bK0k2HER3wS\r
+ SoDA==\r
+X-Received: by 10.194.59.137 with SMTP id z9mr25820928wjq.28.1445936731562;\r
+ Tue, 27 Oct 2015 02:05:31 -0700 (PDT)\r
+Received: from localhost (5751dfa2.skybroadband.com. [87.81.223.162])\r
+ by smtp.gmail.com with ESMTPSA id q8sm16965563wiz.23.2015.10.27.02.05.30\r
+ (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\r
+ Tue, 27 Oct 2015 02:05:31 -0700 (PDT)\r
+From: Mark Walters <markwalters1009@gmail.com>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH (draft)] company model for external programs\r
+Date: Tue, 27 Oct 2015 09:05:28 +0000\r
+Message-Id: <1445936728-30840-1-git-send-email-markwalters1009@gmail.com>\r
+X-Mailer: git-send-email 2.1.4\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.20\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch/>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Tue, 27 Oct 2015 09:05:37 -0000\r
+\r
+---\r
+\r
+This is an attempt to make company mode work for external address\r
+completion programs. We need to be able to run the address completion\r
+asynchronously.\r
+\r
+The changes are three fold: separate out the internal completion code\r
+into its own function, allow the external program to be called\r
+asynchronously, and copy the relevant code from the emacs function\r
+process-lines into our function as it doesn't appear to be available\r
+as a separate function.\r
+\r
+It seems to work in light testing but asynchronous emacs is always a\r
+little fragile/tricky.\r
+\r
+Best wishes\r
+\r
+Mark\r
+\r
+\r
+\r
+emacs/notmuch-address.el |  2 +-\r
+ emacs/notmuch-company.el | 65 +++++++++++++++++++++++++++++++++++++-----------\r
+ 2 files changed, 51 insertions(+), 16 deletions(-)\r
+\r
+diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el\r
+index 49e2402..65d04ce 100644\r
+--- a/emacs/notmuch-address.el\r
++++ b/emacs/notmuch-address.el\r
+@@ -81,7 +81,7 @@ (defcustom notmuch-address-use-company t\r
\r
+ (defun notmuch-address-setup ()\r
+   (let* ((use-company (and notmuch-address-use-company\r
+-                         (eq notmuch-address-command 'internal)\r
++              ;;         (eq notmuch-address-command 'internal)\r
+                          (require 'company nil t)))\r
+        (pair (cons notmuch-address-completion-headers-regexp\r
+                    (if use-company\r
+diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el\r
+index add3161..dc3d018 100644\r
+--- a/emacs/notmuch-company.el\r
++++ b/emacs/notmuch-company.el\r
+@@ -42,6 +42,7 @@ (defvar company-backends)\r
+ (declare-function notmuch-address-matching "notmuch-address")\r
+ (defvar notmuch-address-full-harvest-finished)\r
+ (defvar notmuch-address-completion-headers-regexp)\r
++(defvar notmuch-address-command)\r
\r
+ ;;;###autoload\r
+ (defun notmuch-company-setup ()\r
+@@ -49,6 +50,54 @@ (defun notmuch-company-setup ()\r
+   (make-local-variable 'company-backends)\r
+   (setq company-backends '(notmuch-company)))\r
\r
++(defun notmuch-company-address-internal (arg)\r
++  (cond\r
++   (notmuch-address-full-harvest-finished\r
++    ;; Update harvested addressed from time to time\r
++    (notmuch-address-harvest-trigger)\r
++    (notmuch-address-matching arg))\r
++   (t\r
++    (cons :async\r
++        (lambda (callback)\r
++          ;; First run quick asynchronous harvest based on what the user entered so far\r
++          (notmuch-address-harvest\r
++           (format "to:%s*" arg) nil\r
++           (lambda (_proc _event)\r
++             (funcall callback (notmuch-address-matching arg))\r
++             ;; Then start the (potentially long-running) full asynchronous harvest if necessary\r
++             (notmuch-address-harvest-trigger))))))))\r
++\r
++(defun notmuch-company-external-sentinel (callback proc _event)\r
++  (let (lines)\r
++    (with-current-buffer (process-buffer proc)\r
++      ;; Copied verbatim from the process-lines function in subr.el in\r
++      ;; the standard emacs distribution.\r
++      (goto-char (point-min))\r
++      (while (not (eobp))\r
++      (setq lines (cons (buffer-substring-no-properties\r
++                         (line-beginning-position)\r
++                         (line-end-position))\r
++                        lines))\r
++      (forward-line 1))\r
++      (message "lines %s" lines))\r
++    (kill-buffer (process-buffer proc))\r
++    (funcall callback (nreverse lines))))\r
++\r
++(defun notmuch-company-address-external (arg)\r
++  (cons :async\r
++      (lambda (callback)\r
++        (let* ((buf (generate-new-buffer " *notmuch-external-address*"))\r
++               (proc (start-process "notmuch-external-address" buf\r
++                                    notmuch-address-command arg)))\r
++          (set-process-sentinel proc (apply-partially\r
++                                      'notmuch-company-external-sentinel\r
++                                      callback))))))\r
++\r
++(defun notmuch-company-address (arg)\r
++  (if (eq notmuch-address-command 'internal)\r
++      (notmuch-company-address-internal arg)\r
++    (notmuch-company-address-external arg)))\r
++\r
+ ;;;###autoload\r
+ (defun notmuch-company (command &optional arg &rest _ignore)\r
+   "`company-mode' completion back-end for `notmuch'."\r
+@@ -62,21 +111,7 @@ (defun notmuch-company (command &optional arg &rest _ignore)\r
+                  (looking-back (concat notmuch-address-completion-headers-regexp ".*")\r
+                                (line-beginning-position))\r
+                  (setq notmuch-company-last-prefix (company-grab "[:,][ \t]*\\(.*\\)" 1 (point-at-bol)))))\r
+-      (candidates (cond\r
+-                 (notmuch-address-full-harvest-finished\r
+-                  ;; Update harvested addressed from time to time\r
+-                  (notmuch-address-harvest-trigger)\r
+-                  (notmuch-address-matching arg))\r
+-                 (t\r
+-                  (cons :async\r
+-                        (lambda (callback)\r
+-                          ;; First run quick asynchronous harvest based on what the user entered so far\r
+-                          (notmuch-address-harvest\r
+-                           (format "to:%s*" arg) nil\r
+-                           (lambda (_proc _event)\r
+-                             (funcall callback (notmuch-address-matching arg))\r
+-                             ;; Then start the (potentially long-running) full asynchronous harvest if necessary\r
+-                             (notmuch-address-harvest-trigger))))))))\r
++      (candidates (notmuch-company-address arg))\r
+       (match (if (string-match notmuch-company-last-prefix arg)\r
+                (match-end 0)\r
+              0))\r
+-- \r
+2.1.4\r
+\r