* Re: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function [not found] ` <20180323044823.1A70C20BDE@vcs0.savannah.gnu.org> @ 2018-03-23 5:18 ` Stefan Monnier 2018-03-23 5:50 ` Eric Abrahamsen 0 siblings, 1 reply; 14+ messages in thread From: Stefan Monnier @ 2018-03-23 5:18 UTC (permalink / raw) To: emacs-devel; +Cc: Eric Abrahamsen > +;; Experimental completion-at-point function. I'm not sure this is a > +;; good idea yet -- with a large enough EBDB database, nearly any > +;; string is completable, meaning the other completion-at-point > +;; functions will rarely get a chance. > +(defun ebdb-completion-at-point-function () [...] > + (when completions > + (list start (point) > + (mapcar > + (lambda (str) > + ;; Gross. > + (if (string-match-p "@" str) > + str > + (capitalize str))) > + completions) > + '(:exclusive no))))) Completion-at-point-functions are expected to be cheap/fast (it's normal to call it in post-command-hook) and in order to work correctly the completion table it returns should ideally not depend on the text between START and END (i.e. it's OK to look at the text between START..END in order to choose between an email completion table and a file completion table, but it shouldn't throw away emails just because they don't seem to match the text between START..END). Also in order to be effective, you want them to be selective, e.g. only match when we're pretty sure that the completion-table we return is relevant (e.g. we're on a "To:" line in a message-mode buffer), so it usually depends on the major mode in which it's used. EBDB might elect not to provide a completion-at-point-function but instead to provide only a completion-table (or a bunch of completion tables). Then message-mode could use that completion-table when it determines that we're completing an email address. Stefan ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function 2018-03-23 5:18 ` [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function Stefan Monnier @ 2018-03-23 5:50 ` Eric Abrahamsen 2018-03-23 10:54 ` Thomas Fitzsimmons ` (2 more replies) 0 siblings, 3 replies; 14+ messages in thread From: Eric Abrahamsen @ 2018-03-23 5:50 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@IRO.UMontreal.CA> writes: >> +;; Experimental completion-at-point function. I'm not sure this is a >> +;; good idea yet -- with a large enough EBDB database, nearly any >> +;; string is completable, meaning the other completion-at-point >> +;; functions will rarely get a chance. >> +(defun ebdb-completion-at-point-function () > [...] >> + (when completions >> + (list start (point) >> + (mapcar >> + (lambda (str) >> + ;; Gross. >> + (if (string-match-p "@" str) >> + str >> + (capitalize str))) >> + completions) >> + '(:exclusive no))))) > Completion-at-point-functions are expected to be cheap/fast (it's normal > to call it in post-command-hook) and in order to work correctly the > completion table it returns should ideally not depend on the text > between START and END (i.e. it's OK to look at the text between > START..END in order to choose between an email completion table and > a file completion table, but it shouldn't throw away emails just > because they don't seem to match the text between START..END). > > Also in order to be effective, you want them to be selective, e.g. only > match when we're pretty sure that the completion-table we return is > relevant (e.g. we're on a "To:" line in a message-mode buffer), so it > usually depends on the major mode in which it's used. > > EBDB might elect not to provide a completion-at-point-function but > instead to provide only a completion-table (or a bunch of completion > tables). Then message-mode could use that completion-table when it > determines that we're completing an email address. Thanks for these notes! In part I was wondering if it would be useful to provide completion on contact names in other contexts besides message headers, but I suppose the right thing to do is just add contact names to the user's personal spelling dictionary, and allow them to complete names as part of spell-checking/ispell-complete-word. EBDB provides other tools for inserting contact information in random contexts. So this completion function should be targeted specifically at message/mail-mode header lines. I'll no longer override <TAB> in that message-mode, but instead tie into what's already there. In message-mode, c-a-p-f contains `message-completion-function', which consults `message-completion-alist' (which contains a FIXME: "Make it possible to use the standard completion UI."), which hands off to `message-expand-name', which is hard-coded to use either eudc, bbdb, or `expand-abbrev'. There is a user option, `message-expand-name-databases', but it's mostly useless as putting new databases in there won't actually let you use them. Looks like you added that FIXME! If you outline how you think this ought to look, I can take a stab at patching message.el. At what level should these functions be intervening? My only reservation is that BBDB/EBDB mail completion first completes a contact mail address, and subsequently cycles through that contact's other addresses. Is this something that the standard mechanisms can replicate? Thanks, Eric ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function 2018-03-23 5:50 ` Eric Abrahamsen @ 2018-03-23 10:54 ` Thomas Fitzsimmons 2018-03-23 12:10 ` Eric Abrahamsen 2018-03-23 12:11 ` Eric Abrahamsen 2018-03-23 12:23 ` Stefan Monnier 2 siblings, 1 reply; 14+ messages in thread From: Thomas Fitzsimmons @ 2018-03-23 10:54 UTC (permalink / raw) To: Eric Abrahamsen; +Cc: emacs-devel Eric Abrahamsen <eric@ericabrahamsen.net> writes: > Stefan Monnier <monnier@IRO.UMontreal.CA> writes: > >>> +;; Experimental completion-at-point function. I'm not sure this is a >>> +;; good idea yet -- with a large enough EBDB database, nearly any >>> +;; string is completable, meaning the other completion-at-point >>> +;; functions will rarely get a chance. See also: eudc-expand-inline, which works at point as long as the to-be-completed string is the only thing between beginning-of-line and point. This is what I use for inline BBDB and LDAP completion anywhere in Emacs, not just in message-mode headers. It's useful, for example, when adding someone's email address to an Org-mode entry (type a few letters of their first name, then M-x eudc-expand-inline). Maybe we could add an EBDB backend for EUDC. Thomas ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function 2018-03-23 10:54 ` Thomas Fitzsimmons @ 2018-03-23 12:10 ` Eric Abrahamsen 0 siblings, 0 replies; 14+ messages in thread From: Eric Abrahamsen @ 2018-03-23 12:10 UTC (permalink / raw) To: Thomas Fitzsimmons; +Cc: emacs-devel Thomas Fitzsimmons <fitzsim@fitzsim.org> writes: > Eric Abrahamsen <eric@ericabrahamsen.net> writes: > >> Stefan Monnier <monnier@IRO.UMontreal.CA> writes: >> >>>> +;; Experimental completion-at-point function. I'm not sure this is a >>>> +;; good idea yet -- with a large enough EBDB database, nearly any >>>> +;; string is completable, meaning the other completion-at-point >>>> +;; functions will rarely get a chance. > > See also: eudc-expand-inline, which works at point as long as the > to-be-completed string is the only thing between beginning-of-line and > point. This is what I use for inline BBDB and LDAP completion anywhere > in Emacs, not just in message-mode headers. It's useful, for example, > when adding someone's email address to an Org-mode entry (type a few > letters of their first name, then M-x eudc-expand-inline). > > Maybe we could add an EBDB backend for EUDC. To be honest, I never looked at what EUDC actually is. I'd be happy to add an EBDB backend, I'll put that on the list. Eric ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function 2018-03-23 5:50 ` Eric Abrahamsen 2018-03-23 10:54 ` Thomas Fitzsimmons @ 2018-03-23 12:11 ` Eric Abrahamsen 2018-03-23 12:23 ` Stefan Monnier 2 siblings, 0 replies; 14+ messages in thread From: Eric Abrahamsen @ 2018-03-23 12:11 UTC (permalink / raw) To: emacs-devel Eric Abrahamsen <eric@ericabrahamsen.net> writes: > Stefan Monnier <monnier@IRO.UMontreal.CA> writes: > >>> +;; Experimental completion-at-point function. I'm not sure this is a >>> +;; good idea yet -- with a large enough EBDB database, nearly any >>> +;; string is completable, meaning the other completion-at-point >>> +;; functions will rarely get a chance. >>> +(defun ebdb-completion-at-point-function () >> [...] >>> + (when completions >>> + (list start (point) >>> + (mapcar >>> + (lambda (str) >>> + ;; Gross. >>> + (if (string-match-p "@" str) >>> + str >>> + (capitalize str))) >>> + completions) >>> + '(:exclusive no))))) >> Completion-at-point-functions are expected to be cheap/fast (it's normal >> to call it in post-command-hook) and in order to work correctly the >> completion table it returns should ideally not depend on the text >> between START and END (i.e. it's OK to look at the text between >> START..END in order to choose between an email completion table and >> a file completion table, but it shouldn't throw away emails just >> because they don't seem to match the text between START..END). >> >> Also in order to be effective, you want them to be selective, e.g. only >> match when we're pretty sure that the completion-table we return is >> relevant (e.g. we're on a "To:" line in a message-mode buffer), so it >> usually depends on the major mode in which it's used. >> >> EBDB might elect not to provide a completion-at-point-function but >> instead to provide only a completion-table (or a bunch of completion >> tables). Then message-mode could use that completion-table when it >> determines that we're completing an email address. [...] > My only reservation is that BBDB/EBDB mail completion first completes a > contact mail address, and subsequently cycles through that contact's > other addresses. Is this something that the standard mechanisms can > replicate? Never mind, obviously the completion functions can do whatever they like with the string to be completed. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function 2018-03-23 5:50 ` Eric Abrahamsen 2018-03-23 10:54 ` Thomas Fitzsimmons 2018-03-23 12:11 ` Eric Abrahamsen @ 2018-03-23 12:23 ` Stefan Monnier 2018-04-14 1:02 ` Completion functions in message-mode (was: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function) Eric Abrahamsen 2 siblings, 1 reply; 14+ messages in thread From: Stefan Monnier @ 2018-03-23 12:23 UTC (permalink / raw) To: emacs-devel > Looks like you added that FIXME! If you outline how you think this ought > to look, I can take a stab at patching message.el. At what level should > these functions be intervening? One of the main issue is preserving backward compatibility with existing functions the user may have set in message-completion-alist. I have already some local patches to try and do some of that, so see patch below (I hand-edited it to remove irrelevant other cosmetic changes, so don't try to pass it to `patch`). > My only reservation is that BBDB/EBDB mail completion first completes a > contact mail address, and subsequently cycles through that contact's > other addresses. Is this something that the standard mechanisms can > replicate? You can get cycling via completion-cycle-threshold, yes. Stefan diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index e452c80e26..c99708845d 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -7930,6 +7936,8 @@ message-tab (defvar mail-abbrev-mode-regexp) +(defvar message--old-style-completion-functions nil) + (defun message-completion-function () (let ((alist message-completion-alist)) (while (and alist @@ -7938,9 +7946,21 @@ message-completion-function (setq alist (cdr alist))) (when (cdar alist) (let ((fun (cdar alist))) - ;; Even if completion fails, return a non-nil value, so as to avoid - ;; falling back to message-tab-body-function. - (lambda () (funcall fun) 'completion-attempted))))) + (if (member fun message--old-style-completion-functions) + ;; Even if completion fails, return a non-nil value, so as to avoid + ;; falling back to message-tab-body-function. + (lambda () (funcall fun) 'completion-attempted) + (let ((ticks-before (buffer-chars-modified-tick)) + (data (funcall fun))) + (if (and (eq ticks-before (buffer-chars-modified-tick)) + (or (null data) + (integerp (car-safe data)))) + data + (push fun message--old-style-completion-functions) + ;; Completion was already performed, so just return a dummy + ;; function that prevents trying any further. + (lambda () 'completion-attempted)))))))) + (defun message-expand-group () "Expand the group name under point." @@ -7966,7 +8083,9 @@ message-expand-group group) collection)) gnus-active-hashtb)) - (completion-in-region b e collection))) + ;; FIXME: Add `category' metadata to the collection, so we can use + ;; substring matching on it. + (list b e collection))) (defun message-expand-name () (cond ((and (memq 'eudc message-expand-name-databases) ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Completion functions in message-mode (was: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function) 2018-03-23 12:23 ` Stefan Monnier @ 2018-04-14 1:02 ` Eric Abrahamsen 2018-04-14 1:17 ` Completion functions in message-mode Stefan Monnier 2018-04-14 12:59 ` Lars Ingebrigtsen 0 siblings, 2 replies; 14+ messages in thread From: Eric Abrahamsen @ 2018-04-14 1:02 UTC (permalink / raw) To: Stefan Monnier; +Cc: Lars Ingebrigtsen, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Looks like you added that FIXME! If you outline how you think this ought >> to look, I can take a stab at patching message.el. At what level should >> these functions be intervening? > > One of the main issue is preserving backward compatibility with existing > functions the user may have set in message-completion-alist. > > I have already some local patches to try and do some of that, so see > patch below (I hand-edited it to remove irrelevant other cosmetic > changes, so don't try to pass it to `patch`). Okay, I'm finally coming back around to this, and I need a bit more of an overview to know what to do. Lars seems to have come in from the cold, so I'm copying him here. Leaving backward compatibility aside for a second, here's my take on things: What we've got is: message-mode binds TAB to `message-tab', which calls `completion-at-point' and, if that doesn't work, falls back to other things. message-mode adds `message-completion-function' to `completion-functions-at-point', so TAB ends up calling that function first. If point is in a viable header, the function calls `message-expand-group' or `message-expand-name' depending on the header, but either way _always_ returns a value so that it prevents any other capf functions from running. If point isn't in a viable header, we get the "falls back to other things" behavior. `message-expand-name' is the one that hands off to EUDC, BBDB, etc. The whole issue is that these package functions do their own completion, rather than interfacing with `completion-at-point'. What we _want_ is (and I'm partially guessing here): message-mode adds message-expand-group and message-tab-body-function to `completion-at-point-functions'. Both of these functions check if they're in an appropriate location, and bail if not, allowing other functions to do their thing. Packages such as EUDC and BBDB put their own functions in `completion-at-point-functions' (in the message-mode hook). The first thing these functions do is test if they're in an appropriate header, and bail if not. Otherwise they return an appropriate value for c-a-p, ie (START END COLLECTION), rather than doing their own completion. Does this seem about right? Backwards compatibility is still an issue, but that's what Stefan's patch addresses. Eric ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Completion functions in message-mode 2018-04-14 1:02 ` Completion functions in message-mode (was: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function) Eric Abrahamsen @ 2018-04-14 1:17 ` Stefan Monnier 2018-04-14 2:33 ` Eric Abrahamsen 2018-04-14 12:59 ` Lars Ingebrigtsen 1 sibling, 1 reply; 14+ messages in thread From: Stefan Monnier @ 2018-04-14 1:17 UTC (permalink / raw) To: emacs-devel > message-mode adds message-expand-group and message-tab-body-function to > `completion-at-point-functions'. Both of these functions check if > they're in an appropriate location, and bail if not, allowing other > functions to do their thing. I think it's OK for Gnus to keep using message-completion-alist, but message-expand-name should use a completion table which can be extended, so EUDC, BBDB, ecomplete, and YouNameIt can add themselves to it. > Packages such as EUDC and BBDB put their own functions in > `completion-at-point-functions' (in the message-mode hook). That doesn't sound right: the code which decides if we're inside a message header, and which header contains email addresses, and how they're separated (i.e. the code which knows about the format of messages) should squarely belong to message-mode and not to BBDB/EUDC/... Instead these backends should only provide completion tables that provide user names, email addresses, or such data. I.e. the completion-at-point-function should come from message.el and the completion-tables it returns should come from BBDB/EUDC/... Stefan ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Completion functions in message-mode 2018-04-14 1:17 ` Completion functions in message-mode Stefan Monnier @ 2018-04-14 2:33 ` Eric Abrahamsen 2018-04-14 17:37 ` Stefan Monnier 0 siblings, 1 reply; 14+ messages in thread From: Eric Abrahamsen @ 2018-04-14 2:33 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> message-mode adds message-expand-group and message-tab-body-function to >> `completion-at-point-functions'. Both of these functions check if >> they're in an appropriate location, and bail if not, allowing other >> functions to do their thing. > > I think it's OK for Gnus to keep using message-completion-alist, but > message-expand-name should use a completion table which can be extended, > so EUDC, BBDB, ecomplete, and YouNameIt can add themselves to it. > >> Packages such as EUDC and BBDB put their own functions in >> `completion-at-point-functions' (in the message-mode hook). > > That doesn't sound right: the code which decides if we're inside > a message header, and which header contains email addresses, and how > they're separated (i.e. the code which knows about the format of > messages) should squarely belong to message-mode and not to > BBDB/EUDC/... > > Instead these backends should only provide completion tables that > provide user names, email addresses, or such data. > > I.e. the completion-at-point-function should come from message.el and > the completion-tables it returns should come from BBDB/EUDC/... Good! Thanks, that's the direction I needed. My next question is, how does one "extend" a completion table? Specifically: if c-a-p expects to receive (START END COLLECTION), should the message-mode capf function marshal collections from various backends, and offer them up as part of that one return value? So say we add a message-name-completion-functions option, each backend adds its function there, and message-mode calls all those functions, gathers the results, and returns them to `completion-at-point'? Almost there, Eric ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Completion functions in message-mode 2018-04-14 2:33 ` Eric Abrahamsen @ 2018-04-14 17:37 ` Stefan Monnier 2018-04-25 19:24 ` Eric Abrahamsen 0 siblings, 1 reply; 14+ messages in thread From: Stefan Monnier @ 2018-04-14 17:37 UTC (permalink / raw) To: emacs-devel > My next question is, how does one "extend" a completion table? Not sure what you mean, but you can combine completion tables for example by using completion-table-in-turn, or by doing something similar to what it does. > Specifically: if c-a-p expects to receive (START END COLLECTION), should ^^^^^^^^^^ BTW, this is what I call "completion table". Stefan ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Completion functions in message-mode 2018-04-14 17:37 ` Stefan Monnier @ 2018-04-25 19:24 ` Eric Abrahamsen 2018-06-06 21:09 ` Eric Abrahamsen 0 siblings, 1 reply; 14+ messages in thread From: Eric Abrahamsen @ 2018-04-25 19:24 UTC (permalink / raw) To: emacs-devel; +Cc: Stefan Monnier [-- Attachment #1: Type: text/plain, Size: 1398 bytes --] Stefan Monnier <monnier@iro.umontreal.ca> writes: >> My next question is, how does one "extend" a completion table? > > Not sure what you mean, but you can combine completion tables for > example by using completion-table-in-turn, or by doing something > similar to what it does. Yes, that's what I meant. >> Specifically: if c-a-p expects to receive (START END COLLECTION), should > ^^^^^^^^^^ > BTW, this is what I call "completion table". Right, that much I understood. But otherwise I was very undereducated about how completion works, and so have gone down some rabbit holes in the course of writing the attached patch, which is underwhelming for how long it took me. I doubt this will be acceptable as-is, but I do hope it will get us (me) a step closer. What I ended up with was an option, `message-expand-name-tables', that contact-management/addressbook packages can add completion tables to. This is very simple, but probably too simple: it leaves no mechanism for these packages to add extra PROPS data, like :predicate or :annotation, and also doesn't give them the opportunity to alter START and END (though maybe it shouldn't?). Anyway, for what it is, it works. It also add six spurious blank spaces to the end of any completion, at least in my test setup, but who's counting!? Hopefully we can go somewhere from here. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: message-completion.diff --] [-- Type: text/x-patch, Size: 6872 bytes --] diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 33c5e2cedb..3a8e3f6e0f 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -7929,24 +7929,33 @@ message-make-tool-bar 'message-mode-map)))) message-tool-bar-map) -;;; Group name completion. +;;; Group and mail name completion. (defcustom message-newgroups-header-regexp "^\\(Newsgroups\\|Followup-To\\|Posted-To\\|Gcc\\):" - "Regexp that match headers that lists groups." + "Regexp matching headers that list groups." :group 'message :type 'regexp) +(defcustom message-mail-header-regexp + (concat + "^" + (regexp-opt + '("To" "Bcc" "Cc" "Resent-To" "Resent-Bcc" "Resent-Cc" + "Reply-To" "From" "Mail-Followup-To" "Mail-Copies-To" + "Disposition-Notification-To" "Return-Receipt-To")) + ":") + "Regexp matching headers that list name/mail addresses." + :group 'message + :type 'regexp + :version "27.1") + (defcustom message-completion-alist - ;; FIXME: Make it possible to use the standard completion UI. - (list (cons message-newgroups-header-regexp 'message-expand-group) - '("^\\(Resent-\\)?\\(To\\|B?Cc\\):" . message-expand-name) - '("^\\(Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):" - . message-expand-name) - '("^\\(Disposition-Notification-To\\|Return-Receipt-To\\):" - . message-expand-name)) - "Alist of (RE . FUN). Use FUN for completion on header lines matching RE." - :version "22.1" + (list (cons message-newgroups-header-regexp #'message-expand-group) + (cons message-mail-header-regexp #'message-expand-name)) + "Alist of (RE . FUN). +Use FUN for completion on header lines matching RE." + :version "27.1" :group 'message :type '(alist :key-type regexp :value-type function)) @@ -7956,6 +7965,19 @@ message-expand-name-databases Each element is a symbol and can be `bbdb' or `eudc'." :group 'message :type '(set (const bbdb) (const eudc))) +(make-obsolete-variable + 'message-expand-name-databases + "Add completion tables to `message-expand-name-tables' instead" + "27.1") + +(defcustom message-expand-name-tables nil + "List of tables that can be used to expand names. +Each \"table\" is a collection containing potential expansions, +and can be an alist, a plain list, a hash table, an obarray, or a +function. Multiple tables will be merged." + :group 'message + :version "27.1" + :type 'list) (defcustom message-tab-body-function nil "Function to execute when `message-tab' (TAB) is executed in the body. @@ -7982,24 +8004,16 @@ message-tab (message-tab-body-function (funcall message-tab-body-function)) (t (funcall (or (lookup-key text-mode-map "\t") (lookup-key global-map "\t") - 'indent-relative))))) + #'indent-relative))))) (defvar mail-abbrev-mode-regexp) -(defun message-completion-function () - (let ((alist message-completion-alist)) - (while (and alist - (let ((mail-abbrev-mode-regexp (caar alist))) - (not (mail-abbrev-in-expansion-header-p)))) - (setq alist (cdr alist))) - (when (cdar alist) - (let ((fun (cdar alist))) - ;; Even if completion fails, return a non-nil value, so as to avoid - ;; falling back to message-tab-body-function. - (lambda () (funcall fun) 'completion-attempted))))) +(defvar message--old-style-completion-functions nil) -(defun message-expand-group () - "Expand the group name under point." +(defsubst message-header-completion-bounds () + "Return the bounds of header input for completion. +Searches back for either the end of header or the nearest comma, +and forward for either the nearest comma or EOL." (let ((b (save-excursion (save-restriction (narrow-to-region @@ -8009,36 +8023,57 @@ message-expand-group (1+ (point))) (point)) (skip-chars-backward "^, \t\n") (point)))) - (completion-ignore-case t) - (e (progn (skip-chars-forward "^,\t\n ") (point))) - group collection) - (when (and (boundp 'gnus-active-hashtb) - gnus-active-hashtb) - (mapatoms - (lambda (symbol) - (setq group (symbol-name symbol)) - (push (if (string-match "[^\000-\177]" group) - (gnus-group-decoded-name group) - group) - collection)) - gnus-active-hashtb)) - (completion-in-region b e collection))) + (e (progn (skip-chars-forward "^,\t\n ") (point)))) + (cons b e))) + +(defun message-completion-function () + "Possibly complete a group name or mail address. +Check if point is in an appropriate header for completion, +otherwise return nil." + (let ((alist message-completion-alist)) + (while (and alist + (let ((mail-abbrev-mode-regexp (caar alist))) + (not (mail-abbrev-in-expansion-header-p)))) + (setq alist (cdr alist))) + (when (cdar alist) + (let ((fun (cdar alist)) + (completion-ignore-case t)) + (if (member fun message--old-style-completion-functions) + ;; Even if completion fails, return a non-nil value, so as to avoid + ;; falling back to message-tab-body-function. + (lambda () (funcall fun) 'completion-attempted) + (let ((ticks-before (buffer-chars-modified-tick)) + (data (funcall fun))) + (if (and (eq ticks-before (buffer-chars-modified-tick)) + (or (null data) + (integerp (car-safe data)))) + data + (push fun message--old-style-completion-functions) + ;; Completion was already performed, so just return a dummy + ;; function that prevents trying any further. + (lambda () 'completion-attempted)))))))) + +(defun message-expand-group () + "Return group completion from `gnus-active-hashtb'." + (pcase-let ((`(,b . ,e) (message-header-completion-bounds))) + (let (collection group) + (when (and (boundp 'gnus-active-hashtb) + gnus-active-hashtb) + (mapatoms + (lambda (symbol) + (setq group (symbol-name symbol)) + (push (if (string-match "[^\000-\177]" group) + (gnus-group-decoded-name group) + group) + collection)) + gnus-active-hashtb) + (list b e collection))))) (defun message-expand-name () - (cond ((and (memq 'eudc message-expand-name-databases) - (boundp 'eudc-protocol) - eudc-protocol) - (eudc-expand-inline)) - ((and (memq 'bbdb message-expand-name-databases) - (fboundp 'bbdb-complete-name)) - (let ((starttick (buffer-modified-tick))) - (or (bbdb-complete-name) - ;; Apparently, bbdb-complete-name can return nil even when - ;; completion took place. So let's double check the buffer was - ;; not modified. - (/= starttick (buffer-modified-tick))))) - (t - (expand-abbrev)))) + (pcase-let ((`(,b . ,e) (message-header-completion-bounds))) + (when message-expand-name-tables + (list b e (apply #'completion-table-in-turn + message-expand-name-tables))))) ;;; Help stuff. ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: Completion functions in message-mode 2018-04-25 19:24 ` Eric Abrahamsen @ 2018-06-06 21:09 ` Eric Abrahamsen 0 siblings, 0 replies; 14+ messages in thread From: Eric Abrahamsen @ 2018-06-06 21:09 UTC (permalink / raw) To: emacs-devel; +Cc: Stefan Monnier Eric Abrahamsen <eric@ericabrahamsen.net> writes: > Stefan Monnier <monnier@iro.umontreal.ca> writes: > >>> My next question is, how does one "extend" a completion table? >> >> Not sure what you mean, but you can combine completion tables for >> example by using completion-table-in-turn, or by doing something >> similar to what it does. > > Yes, that's what I meant. > >>> Specifically: if c-a-p expects to receive (START END COLLECTION), should >> ^^^^^^^^^^ >> BTW, this is what I call "completion table". > > Right, that much I understood. But otherwise I was very undereducated > about how completion works, and so have gone down some rabbit holes in > the course of writing the attached patch, which is underwhelming for how > long it took me. Was this too off-base? Is there any chance I could bang it into usable shape? ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Completion functions in message-mode 2018-04-14 1:02 ` Completion functions in message-mode (was: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function) Eric Abrahamsen 2018-04-14 1:17 ` Completion functions in message-mode Stefan Monnier @ 2018-04-14 12:59 ` Lars Ingebrigtsen 2018-04-14 16:17 ` Eric Abrahamsen 1 sibling, 1 reply; 14+ messages in thread From: Lars Ingebrigtsen @ 2018-04-14 12:59 UTC (permalink / raw) To: Eric Abrahamsen; +Cc: Stefan Monnier, emacs-devel Eric Abrahamsen <eric@ericabrahamsen.net> writes: > message-mode adds message-expand-group and message-tab-body-function to > `completion-at-point-functions'. Both of these functions check if > they're in an appropriate location, and bail if not, allowing other > functions to do their thing. Does this also tie into ecomplete somehow? :-) -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Completion functions in message-mode 2018-04-14 12:59 ` Lars Ingebrigtsen @ 2018-04-14 16:17 ` Eric Abrahamsen 0 siblings, 0 replies; 14+ messages in thread From: Eric Abrahamsen @ 2018-04-14 16:17 UTC (permalink / raw) To: Lars Ingebrigtsen; +Cc: Stefan Monnier, emacs-devel Lars Ingebrigtsen <larsi@gnus.org> writes: > Eric Abrahamsen <eric@ericabrahamsen.net> writes: > >> message-mode adds message-expand-group and message-tab-body-function to >> `completion-at-point-functions'. Both of these functions check if >> they're in an appropriate location, and bail if not, allowing other >> functions to do their thing. > > Does this also tie into ecomplete somehow? :-) I think the goal is that ecomplete would be one of the $contact_packages that can add themselves as sources for completions. But I'm still not sure of the exact mechanism. ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2018-06-06 21:09 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <20180323044822.32467.63948@vcs0.savannah.gnu.org> [not found] ` <20180323044823.1A70C20BDE@vcs0.savannah.gnu.org> 2018-03-23 5:18 ` [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function Stefan Monnier 2018-03-23 5:50 ` Eric Abrahamsen 2018-03-23 10:54 ` Thomas Fitzsimmons 2018-03-23 12:10 ` Eric Abrahamsen 2018-03-23 12:11 ` Eric Abrahamsen 2018-03-23 12:23 ` Stefan Monnier 2018-04-14 1:02 ` Completion functions in message-mode (was: [elpa] externals/ebdb 9e7a96f: Add experimental ebdb-completion-at-point-function) Eric Abrahamsen 2018-04-14 1:17 ` Completion functions in message-mode Stefan Monnier 2018-04-14 2:33 ` Eric Abrahamsen 2018-04-14 17:37 ` Stefan Monnier 2018-04-25 19:24 ` Eric Abrahamsen 2018-06-06 21:09 ` Eric Abrahamsen 2018-04-14 12:59 ` Lars Ingebrigtsen 2018-04-14 16:17 ` Eric Abrahamsen
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).