From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp12.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id eEc5LyW72mKQdQEAbAwnHQ (envelope-from ) for ; Fri, 22 Jul 2022 16:58:45 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp12.migadu.com with LMTPS id oHIOLyW72mJPEgAAauVa8A (envelope-from ) for ; Fri, 22 Jul 2022 16:58:45 +0200 Received: from mail.notmuchmail.org (yantan.tethera.net [IPv6:2a01:4f9:c011:7a79::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 96F65285A for ; Fri, 22 Jul 2022 16:58:45 +0200 (CEST) Received: from yantan.tethera.net (localhost [127.0.0.1]) by mail.notmuchmail.org (Postfix) with ESMTP id 7CFC860813; Fri, 22 Jul 2022 14:58:42 +0000 (UTC) X-Greylist: delayed 496 seconds by postgrey-1.36 at yantan; Fri, 22 Jul 2022 14:58:39 UTC Received: from smtprelay06.ispgateway.de (smtprelay06.ispgateway.de [80.67.18.29]) by mail.notmuchmail.org (Postfix) with ESMTPS id 304305F41E for ; Fri, 22 Jul 2022 14:58:39 +0000 (UTC) Received: from [46.244.207.124] (helo=condition-alpha.com) by smtprelay06.ispgateway.de with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1oEtyz-0003aB-Tp for notmuch@notmuchmail.org; Fri, 22 Jul 2022 16:50:26 +0200 Message-Id: <8a437e3f646f7972c86c4aae57ae7452@condition-alpha.com> From: Alexander Adolf To: notmuch@notmuchmail.org Subject: [Emacs] Using notmuch-address with EUDC, and completion-at-point Date: Fri, 22 Jul 2022 16:50:21 +0200 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Df-Sender: YWxleGFuZGVyLmFkb2xmQGNvbmRpdGlvbi1hbHBoYS5jb20= Message-ID-Hash: MDO7EWBSDZ6FXXU7OCT4TDYDXVFMYILY X-Message-ID-Hash: MDO7EWBSDZ6FXXU7OCT4TDYDXVFMYILY X-MailFrom: alexander.adolf@condition-alpha.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-notmuch.notmuchmail.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.3 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Migadu-Flow: FLOW_IN X-Migadu-To: larch@yhetil.org X-Migadu-Country: DE ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1658501925; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type:list-id: list-help:list-owner:list-unsubscribe:list-subscribe:list-post; bh=C+Oig91MJfEaXVD9uPq9Mk8aQUJaNqpP924OER18jV4=; b=TuFMhUj2VjH+njzlp3SlY4K5gaQySdnrm6kKfrSMwkBhlSG5W3rB+8DASBm5FcgVp8E/rA aQ0+O1S8omN9wvYSiKHoqFm6XcBH2wPkrhhvDR+F6b8XtviLEkbT7fzTVrVDNhVq7egO+h ria7pKpjLL0MVSzqFHzWXLDjwtlxjGti2F5n0JfKzd3CXkzG4yRagH/HguD1VnGNkj+LcO tfgUQyD//0wK1yvyzql5uR8BxHsmWw7RA03IrUktR8zZVlLdHQOGJINcKca9+N3FPWsnkW wCXfwvwaPmXcflrohpPhMyHfnj2qF7ODlOPs/WseIixJ3cYODIeu43sf7BHmHw== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1658501925; a=rsa-sha256; cv=none; b=W3h8ww3wwGKJq/8FPHVHABAN0ZNnwtCqRinzO3YB5AXLuE7tYt+LQQZs3xKQ2yYi1S/Rdb hfvJMW8UHumQcPeqaUgmYTXml1l8u3D9eIdSnVexPOzTfqfPnoaw/5o9waODFCXZAc/8uG eTCdviam0DNWJFXmWQqhdifdOKbZC6thRhpkTimWjDnd6QMm/6SycGU1qKAoEJdA5mTD1D 5JYxI92yOANg5Wxca/SlAo639lvu4cRtS2cJnZDW/yT/RroVlb6RYw3bSwb0VMY1Knf+80 WNmpi2hdq7HVRfmHSPkeCozuUE33g6dow+xE41iz+gz2YQQEx80Du3jzOV6tyw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 2a01:4f9:c011:7a79::1 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org X-Migadu-Spam-Score: -2.63 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 2a01:4f9:c011:7a79::1 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org X-Migadu-Queue-Id: 96F65285A X-Spam-Score: -2.63 X-Migadu-Scanner: scn0.migadu.com X-TUID: 5nCT265zlYwO --=-=-= Content-Type: text/plain Hello, I recently switched in-buffer completion from company [1] to completion-at-point with corfu [2] as the UI. As I wanted email address completion via completion-at-point in message-mode too, I implemented a new EUDC function to go into completion-at-point-functions [3]. [1] https://company-mode.github.io [2] https://github.com/minad/corfu [3] https://github.com/emacs-mirror/emacs/blob/master/lisp/net/eudc-capf.el To close the loop, I also wrote an EUDC back-end to get candidates from notmuch-address (which attached). Now, with a eudc-server-hotlist value of (("localhost" . notmuch-address) ("localhost" . macos-contacts)) and eudc-capf-complete among completion-at-point-functions in message-mode, I get combined email address completion candidates from both sources offered by completion-at-point when composing a new email. Life can be a breeze at times... ;-) I hope anyone else finds this useful. Hoping to have helped, and looking forward to your thoughts, --alexander --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=eudcb-notmuch-address.el Content-Transfer-Encoding: quoted-printable ;;; eudcb-notmuch-address.el --- notmuch-address EUDC backend -*- lexical-b= inding: t -*- ;; Copyright (C) 2022 condition-alpha.com ;; This file is not part of GNU Emacs ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; This library provides an interface to the notmuch-address ;; package as an EUDC data source. ;;; Usage: ;; To load the library, first `require' it: ;; ;; (require 'eudcb-notmuch-address) ;; ;; In the simplest case then just use: ;; ;; (eudc-notmuch-address-set-server "localhost") ;; ;; When using `eudc-server-hotlist', instead use: ;; ;; (add-to-list 'eudc-server-hotlist '("localhost" . notmuch-address)) ;;; Code: (require 'eudc) (require 'mail-parse) ;; hook ourselves into the EUDC framework (eudc-protocol-set 'eudc-query-function 'eudcb-notmuch-address-query-internal 'notmuch-address) (eudc-protocol-set 'eudc-list-attributes-function nil 'notmuch-address) (eudc-protocol-set 'eudc-protocol-attributes-translation-alist nil 'notmuch-address) (eudc-protocol-set 'eudc-protocol-has-default-query-attributes nil 'notmuch-address) (defun eudcb-notmuch-address-query-internal (query &optional _return-attrs) "Query `notmuch-address-options' with QUERY. QUERY is a list of cons cells (ATTR . VALUE) where ATTRs should be valid attribute names. RETURN-ATTRS is a list of attributes to return, defaulting to `eudc-default-return-attributes'." (let (result sres) ;; query notmuch-address for all search strings, merging the results (dolist (term query) (setq sres (append sres (notmuch-address-options (cdr term))))) (setq sres (seq-uniq sres)) ;; parse search results into a result structure for EUDC (dolist (str sres) (let* ((parsed (mail-header-parse-address str t)) (email (car parsed)) (name (cdr parsed))) (if parsed ;; email could be decomposed, push individual fields (push `((email . ,email) ,@(when name (list (cons 'name name)))) result) ;; else, just forward the value as-is (push (list (cons 'email str)) result)))) result)) (defun eudcb-notmuch-address-set-server (dummy) "Set the EUDC server to notmuch-address. The server in DUMMY is not actually used, since this backend always and implicitly connetcs to an instance of notmuch running on the local host." (interactive) (eudc-set-server dummy 'notmuch-address) (message "[eudc] notmuch-address server selected")) (eudc-register-protocol 'notmuch-address) (provide 'eudcb-notmuch-address) ;;; eudcb-notmuch-address.el ends here --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline --=-=-=--