3.4 Inline Query Expansion

3.4.1 Inline Query Expansion Using a Key Binding

Inline query expansion is a powerful method to get completion from your directory servers. The most common usage is for expanding names to email addresses in mail message buffers. The expansion is performed by the command M-x eudc-expand-try-all which is available from the ‘Expand Inline Query Trying All Servers’ menu item but can also be conveniently bound to a key shortcut (see Installation). The operation is controlled by the variables eudc-inline-expansion-format, eudc-inline-query-format, eudc-expanding-overwrites-query and eudc-multiple-match-handling-method.

If the query fails for a server, other servers may be tried successively until one of them finds a match (see Multi-server Queries), or all servers can be tried and all matches returned.

Command: eudc-expand-try-all try-all-servers-p

Query some or all servers and expand the query string before point. The query string consists of the buffer substring from the point back to the preceding comma, colon or beginning of line. eudc-inline-query-format controls how individual words are mapped onto directory attribute names. After querying the server or servers for the given string, the expansion specified by eudc-inline-expansion-format is inserted in the buffer at point. If multiple matches are available, a selection window is displayed. If try-all-servers-p is non-nil then all servers are queried.

Command: eudc-expand-inline save-query-as-kill-p

Query the server and expand the query string before point. The query string consists of the buffer substring from the point back to the preceding comma, colon or beginning of line. eudc-inline-query-format controls how individual words are mapped onto directory attribute names. After querying the server for the given string, the expansion specified by eudc-inline-expansion-format is inserted in the buffer at point. If multiple matches are available, a selection window is displayed. If save-query-as-kill-p is t then the query string is saved to the kill ring. If eudc-expansion-save-query-as-kill is non-nil then the meaning of save-query-as-kill-p is negated.

Variable: eudc-inline-query-format

Format of an inline expansion query. This is actually a list of formats. A format is a list of one or more EUDC attribute names. A format applies if it contains as many attributes as individual words in the inline query string. If several formats apply then they are tried in order until a match is found. If nil all the words will be mapped onto the default server/protocol attribute name (generally name).

For instance, use the following

(setq eudc-inline-query-format '((name)
                                 (firstname)
                                 (firstname name)))

to indicate that single word expansion queries are to be considered as surnames and if no match is found then they should be tried as first names. Inline queries consisting of two words are considered as consisting of a first name followed by a surname. If the query consists of more than two words, then the first one is considered as the first name and the remaining words are all considered as surname constituents.

formats are in fact not limited to EUDC attribute names, you can use server or protocol specific names in them. It may be safer if you do so, to set the variable eudc-inline-query-format in a protocol or server local fashion (see Server/Protocol Locals).

For instance you could use the following to match up to three words against the cn attribute of LDAP servers:

(eudc-protocol-set 'eudc-inline-query-format
                   '((cn)
                     (cn cn)
                     (cn cn cn))
                   'ldap)
Variable: eudc-inline-expansion-format

This variable lets you control exactly what is inserted into the buffer upon an inline expansion request. It can be set to nil, to a function, or to a list. Default is nil.

When the value is a list, the first element is a string passed to format. Remaining elements are symbols corresponding to directory attribute names. The corresponding attribute values are passed as additional arguments to format.

When the value is nil, the expansion result will be formatted according to RFC 5322. The phrase part will be formatted as “firstname name”, quoting the result if necessary. No comment part will be added in this case. This will produce any of the default formats

address
first <address>
last <address>
first last <address>

depending on whether a first and/or last name are returned by the query, or not.

When the value is a function, the expansion result will be formatted according to RFC 5322, and the referenced function is called to format the phrase, and comment parts, respectively. The formatted phrase part will be quoted if necessary. Thus one can produce any of the formats:

address
phrase <address>
address (comment)
phrase <address> (comment)

Email address specifications, as are generated by inline expansion, need to comply with RFC 5322 in order to be useful in email messages. When an invalid address specification is present in an email message header, the message is likely to be rejected by a receiving MTA. It is hence recommended to switch old configurations, which use a list value, to the new nil, or function value type since it ensures that the inserted address specifications will be in line with RFC 5322. At minimum, and to achieve the same semantics as with the old list default value, this variable should now be set to nil:

(customize-set-variable 'eudc-inline-expansion-format nil)

A function value can for example be used to get “last, first <address>” instead of the default “first last <address>”:

(defun my-phrase-last-comma-first (search-res-alist)
  (let* (phrase
	 (my-attrs (eudc-translate-attribute-list '(firstname name)))
	 (first-name (cdr (assq (nth 0 my-attrs) search-res-alist)))
	 (last-name (cdr (assq (nth 1 my-attrs) search-res-alist)))
         (comment nil))
    (setq phrase (concat last-name ", " first-name))
    (cons phrase comment)))

(customize-set-variable 'eudc-inline-expansion-format
                        #'my-phrase-last-comma-first)

To set the comment part, too, instead of nil as in this example, also provide a string as the cdr of the cons being returned. Do not include any double quotes in the phrase part, as they are added automatically if needed. Neither include parentheses in the comment part as they, too, are added automatically.

Variable: eudc-multiple-match-handling-method

This variable controls what to do when multiple entries match a query for an inline expansion. Possible values are:

first

The first match is considered as being the only one, the others are discarded.

select

A selection buffer pops up where you can choose a particular match. This is the default value of the variable.

all

The expansion uses all records successively

abort

An error is signaled. The expansion aborts.

Default is select

3.4.2 Inline Query Expansion Using completion-at-point

In addition to providing a dedicated EUDC function for binding to a key shortcut (see Inline Query Expansion), EUDC also provides a function to contribute search results to the Emacs in-buffer completion system available via the function completion-at-point (see (emacs)Identifier Inquiries) in message-mode buffers (see Message in Message). When using this mechanism, queries are made in the multi-server query mode of operation (see Multi-server Queries).

When a buffer in message-mode is created, EUDC’s inline expansion function is automatically added to the variable completion-at-point-functions. As a result, whenever completion-at-point is invoked in a message-mode buffer, EUDC will be queried for email addresses matching the words before point. Since this will be useful only when editing specific message header fields that require specifying one or more email addresses, an additional check is performed whether point is actually in one of those header fields. Thus, any matching email addresses will be offered for completion in suitable message header fields only, and not in other places, like for example the body of the message.