From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Alexander Adolf Newsgroups: gmane.emacs.devel Subject: Thoughts on Refactoring In-Buffer Completion In message.el Date: Thu, 23 Jun 2022 17:26:49 +0200 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="32186"; mail-complaints-to="usenet@ciao.gmane.io" To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Jun 23 17:28:16 2022 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1o4Okh-0008Ci-5a for ged-emacs-devel@m.gmane-mx.org; Thu, 23 Jun 2022 17:28:15 +0200 Original-Received: from localhost ([::1]:49514 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o4Okf-0003RD-P9 for ged-emacs-devel@m.gmane-mx.org; Thu, 23 Jun 2022 11:28:13 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:39894) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o4OjS-0002G5-Tt for emacs-devel@gnu.org; Thu, 23 Jun 2022 11:26:59 -0400 Original-Received: from smtprelay07.ispgateway.de ([134.119.228.97]:27144) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o4OjP-0000QA-Lk for emacs-devel@gnu.org; Thu, 23 Jun 2022 11:26:58 -0400 Original-Received: from [46.244.212.217] (helo=condition-alpha.com) by smtprelay07.ispgateway.de with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1o4OjH-00084s-1p for emacs-devel@gnu.org; Thu, 23 Jun 2022 17:26:47 +0200 X-Df-Sender: YWxleGFuZGVyLmFkb2xmQGNvbmRpdGlvbi1hbHBoYS5jb20= Received-SPF: pass client-ip=134.119.228.97; envelope-from=alexander.adolf@condition-alpha.com; helo=smtprelay07.ispgateway.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:291538 Archived-At: Hello, message.el is a massive file (some 8600 lines), and I can't claim having read or understood any substantial portion of it. All statements solely rely on the (small) portions of the code around completion in message.el, which I have looked at. Thus, as always in life, I shall be looking froward to standing corrected and enlightened wherever I deserve it. ;-) Regarding in-buffer completion, message-mode is probably a rather specific case as it has succinctly distinct in-buffer completion contexts. Think for instance of a body or subject line, vs. a To header line, vs. a References header line, vs. a Newsgroups header line. Currently, message-mode employs two mechanisms for handling these contextss: =E2=80=A2 Its completion function message-completion-function is registered= in completion-at-point-functions, and marshals the in-buffer completion contexts via the variable message-completion-alist. message-completion-alist in turn configures the (one and only) function to be called for completion candidates in a given context. =E2=80=A2 The completion style to use for email addresses is added to the variable completion-category-defaults. What made me start scratching my head about this, was the wish to combine email address candidates from more than one source, and have them be presented in a single list by completion-at-point. Since EUDC had recently gained the ability to return combined search results from several of its back-ends [1], I put together a new EUDC function that can be added to completion-at-point-functions. My new function gets added to the front of completion-at-point-functions in message-mode, and email address completion candidates from the EUDC back-ends I have configured show up when completion-at-point is triggered [2]. [1] commit 0470a4a939772c4bd25123b15f5eadab41f8bee5 [2] commit 620ac6735520aea97ce49059b0df38ed41930b6b So far so good; this satisfies my immediate use-case. Job done? Looking at [2], you'll notice that I need to check in my new EUDC completion function whether point is actually on a To, Cc, etc. line. Otherwise email addresses would happily be offered as completion candidates in the middle of the subject, or in the body. Having this extra check for an email message header line in EUDC code didn't feel quite right, however. Think "separation of concerns". Further looking at message.el, and how in-buffer completion is handled there, you'll find that there is (more or less) close integration with ecomplete, mailabbrev, EUDC, and bbdb in message.el. Consider, for instance the defun starting at line 8378 of message.el: =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80 =E2=94=82 8377 (defun message--bbdb-query-with-words (words) =E2=94=82 8378 ;; FIXME: This (or something like this) should live on th= e BBDB side. =E2=94=82 8379 (when (fboundp 'bbdb-records) =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80 Listing 1: lisp/gnus/message.el "separation of concerns" example What more should I add? I fully agree with the comment in line 8378. Again, think "separation of concerns". On this backdrop, where would I see room for improvement? Overall, there are a couple of bits an pieces for in-buffer completion in place in message.el already. But it seems they were developed/added independently of each other, and a little more orchestration could perhaps help to make things more flexible, but without reinventing the wheel. 1) In message.el, combine both completion control mechanisms into a single one. At first glance from the end user's point of view, message-completion-alist and completion-category-defaults can be perceived as two distinct mechanisms, and it is not immediately obvious which completion style category applies for which regex in message-completion-alist. Only by inspecting line 8404 in message.el, one can discover which category is used: =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80 =E2=94=82 8398 (defun message--name-table (orig-string) =E2=94=82 8399 (let ((orig-words (split-string orig-string "[ \t]+")) =E2=94=82 8400 eudc-responses =E2=94=82 8401 bbdb-responses) =E2=94=82 8402 (lambda (string pred action) =E2=94=82 8403 (pcase action =E2=94=82 8404 ('metadata '(metadata (category . email))) =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80 Listing 2: lisp/gnus/message.el completion styles handling Thus, I would propose to change message-completion-alist from being alist of (RE . FUN), to become an alist of (RE . PLIST). Two properties for the inner plist would initially defined; one for specifying the completion style, and another one for specifying the completion-at-point-functions. With this, the new default value of message-completion-alist could for example be along the lines of: =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80 =E2=94=82 (defcustom message-completion-alist =E2=94=82 `((,message-newgroups-header-regexp =E2=94=82 . '(:capf-style 'newsgroup =E2=94=82 :capf-funs '(gnus-capf-complete))) ;; hypothetical =E2=94=82 (,message-email-recipient-header-regexp =E2=94=82 . '(:capf-style 'email =E2=94=82 :capf-funs '(eudc-capf-complete)))) ;; exists =E2=94=82 "docstring" =E2=94=82 ) =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80 As an aside: considering the FIXME comment in the function message-expand-group, newsgroup completion would seem to be able to benefit from this change, too. If none of the regular expressions matches, the settings in completion-at-point-functions, and completion-category-defaults/overrides will apply as before, or in other modes. With such an approach, the end user would get a positive assertion as to which completion style is used in each part of a message buffer. 2) Refactor ecomplete, mailabbrev, and bbdb stuff out of message.el as much as possible. As the FIXME comment in listing 1 above suggests, any "query with words" functions, or other ecomplete, mailabbrev, or bbdb specific functions should be in the respective packages themselves ("separation of concerns"). Also, as EUDC performs search result aggregation across sources, these packages should implement EUDC back-ends to provide their results via EUDC. Message.el should thus not interact with any email address database directly, but instead provide a default configuration where completion-at-point queries EUDC for email addresses. In all cases, current default behaviour should be retained as much as reasonably possible, of course. Many thanks and looking forward to your thoughts, -=E2=80=93alexander