* [PATCH] `affixation-function`: Allow only three-element lists
@ 2021-04-25 0:39 Daniel Mendler
2021-04-25 17:46 ` Juri Linkov
0 siblings, 1 reply; 7+ messages in thread
From: Daniel Mendler @ 2021-04-25 0:39 UTC (permalink / raw)
To: emacs-devel; +Cc: Stefan Monnier, Juri Linkov
[-- Attachment #1: Type: text/plain, Size: 375 bytes --]
Regarding our previous discussion: I attached a patch which restricts
the definition of the `affixation-function` such that the returned list
must consist only of three-element lists. Since the
`affixation-function` is part of the widely used `completing-read` API a
simplification is helpful for both authors of completion UIs and authors
of completion tables.
Daniel
[-- Attachment #2: 0001-affixation-function-Allow-only-three-element-list-el.patch --]
[-- Type: text/x-diff, Size: 5302 bytes --]
From 82583ee3afbb1278e664a3e5858a93bc698c370b Mon Sep 17 00:00:00 2001
From: Daniel Mendler <mail@daniel-mendler.de>
Date: Sun, 25 Apr 2021 02:04:23 +0200
Subject: [PATCH] (affixation-function): Allow only three-element list elements
Restrict the definition of the `affixation-function`. The function
must return a list of three element lists. Since the
`affixation-function` is part of the widely used `completing-read` API
a simplification is helpful for both authors of completion UIs and
authors of completion tables.
* doc/lispref/minibuf.texi: Update documentation.
* lisp/minibuffer.el: Update documentation.
(minibuffer-completion-help): Add assertion.
* lisp/simple.el (read-extended-command--affixation): Return
three-element lists.
---
doc/lispref/minibuf.texi | 10 ++++------
lisp/minibuffer.el | 22 ++++++++++++----------
lisp/simple.el | 7 +++++--
3 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index 7cf2fcf68f..28d3afac22 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -1819,12 +1819,10 @@ Completion Variables
@item :affixation-function
The value should be a function to add prefixes and suffixes to
completions. This function must accept one argument, a list of
-completions, and should return such a list of completions where
-each element contains a list of three elements: a completion,
-a prefix string, and a suffix string. When this function
-returns a list of two elements, it is interpreted as a list
-of a completion and a suffix string like in @code{:annotation-function}.
-This function takes priority over @code{:annotation-function}.
+completions, and should return a list of annotated completions. Each
+element of the returned list must be a three-element list, the
+completion, a prefix string, and a suffix string. This function takes
+priority over @code{:annotation-function}.
@item :exit-function
The value should be a function to run after performing completion.
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 98691c2ede..f76ce37030 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -122,10 +122,10 @@ completion-metadata
returns a string to append to STRING.
- `affixation-function': function to prepend/append a prefix/suffix to
entries. Takes one argument (COMPLETIONS) and should return a list
- of completions with a list of either two elements: completion
- and suffix, or three elements: completion, its prefix
- and suffix. This function takes priority over `annotation-function'
- when both are provided, so only this function is used.
+ of annotated completions. The elements of the list must be
+ three-element lists: completion, its prefix and suffix. This
+ function takes priority over `annotation-function' when both are
+ provided, so only this function is used.
- `display-sort-function': function to sort entries in *Completions*.
Takes one argument (COMPLETIONS) and should return a new list
of completions. Can operate destructively.
@@ -1972,11 +1972,11 @@ completion-extra-properties
`:affixation-function': Function to prepend/append a prefix/suffix to
completions. The function must accept one argument, a list of
- completions, and return a list where each element is a list of
- either two elements: a completion, and a suffix, or
- three elements: a completion, a prefix and a suffix.
- This function takes priority over `:annotation-function'
- when both are provided, so only this function is used.
+ completions, and return a list of annotated completions. The
+ elements of the list must be three-element lists: completion, its
+ prefix and suffix. This function takes priority over
+ `:annotation-function' when both are provided, so only this
+ function is used.
`:exit-function': Function to run after completion is performed.
@@ -2110,7 +2110,9 @@ minibuffer-completion-help
(cond
(aff-fun
(setq completions
- (funcall aff-fun completions)))
+ (funcall aff-fun completions))
+ (cl-assert (or (not completions)
+ (= 3 (length (car completions))))))
(ann-fun
(setq completions
(mapcar (lambda (s)
diff --git a/lisp/simple.el b/lisp/simple.el
index 999755a642..26eb8cad7f 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2080,8 +2080,11 @@ read-extended-command--affixation
(obsolete
(format " (%s)" (car obsolete)))
((and binding (not (stringp binding)))
- (format " (%s)" (key-description binding))))))
- (if suffix (list command-name suffix) command-name)))
+ (format " (%s)" (key-description binding)))
+ (t ""))))
+ (put-text-property 0 (length suffix)
+ 'face 'completions-annotations suffix)
+ (list command-name "" suffix)))
command-names)))
(defcustom suggest-key-bindings t
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] `affixation-function`: Allow only three-element lists
2021-04-25 0:39 [PATCH] `affixation-function`: Allow only three-element lists Daniel Mendler
@ 2021-04-25 17:46 ` Juri Linkov
2021-04-25 18:02 ` Daniel Mendler
0 siblings, 1 reply; 7+ messages in thread
From: Juri Linkov @ 2021-04-25 17:46 UTC (permalink / raw)
To: Daniel Mendler; +Cc: Stefan Monnier, emacs-devel
> @@ -2110,7 +2110,9 @@ minibuffer-completion-help
> (cond
> (aff-fun
> (setq completions
> - (funcall aff-fun completions)))
> + (funcall aff-fun completions))
> + (cl-assert (or (not completions)
> + (= 3 (length (car completions))))))
It's surprising to see that you added such artificial restriction.
I expected a change with something more like this:
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index e435d0124a..324a171e66 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2129,7 +2129,7 @@ minibuffer-completion-help
(setq completions
(mapcar (lambda (s)
(let ((ann (funcall ann-fun s)))
- (if ann (list s ann) s)))
+ (if ann (list s "" ann) s)))
completions))))
and then simplify the implementation of completion--insert-strings
by removing all complexity that handled suffix-only completion strings.
> diff --git a/lisp/simple.el b/lisp/simple.el
> index 999755a642..26eb8cad7f 100644
> --- a/lisp/simple.el
> +++ b/lisp/simple.el
> @@ -2080,8 +2080,11 @@ read-extended-command--affixation
> (obsolete
> (format " (%s)" (car obsolete)))
> ((and binding (not (stringp binding)))
> - (format " (%s)" (key-description binding))))))
> - (if suffix (list command-name suffix) command-name)))
> + (format " (%s)" (key-description binding)))
> + (t ""))))
> + (put-text-property 0 (length suffix)
> + 'face 'completions-annotations suffix)
> + (list command-name "" suffix)))
> command-names)))
Why such change only for one particular use of annotations?
Shouldn't completion--insert-strings check if the suffix is an
empty string, and then put the 'completions-annotations' face on it?
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] `affixation-function`: Allow only three-element lists
2021-04-25 17:46 ` Juri Linkov
@ 2021-04-25 18:02 ` Daniel Mendler
2021-04-25 20:34 ` Juri Linkov
0 siblings, 1 reply; 7+ messages in thread
From: Daniel Mendler @ 2021-04-25 18:02 UTC (permalink / raw)
To: Juri Linkov; +Cc: Stefan Monnier, emacs-devel
On 4/25/21 7:46 PM, Juri Linkov wrote:
>> @@ -2110,7 +2110,9 @@ minibuffer-completion-help
>> (cond
>> (aff-fun
>> (setq completions
>> - (funcall aff-fun completions)))
>> + (funcall aff-fun completions))
>> + (cl-assert (or (not completions)
>> + (= 3 (length (car completions))))))
>
> It's surprising to see that you added such artificial restriction.
> I expected a change with something more like this:
>
> and then simplify the implementation of completion--insert-strings
> by removing all complexity that handled suffix-only completion strings.
Yes, this is certainly a less artificial way to restrict the results of
the `affixation-function`. However this works only if you add the
condition on when to add annotation faces as you proposed below.
>> diff --git a/lisp/simple.el b/lisp/simple.el
>> index 999755a642..26eb8cad7f 100644
>> --- a/lisp/simple.el
>> +++ b/lisp/simple.el
>> @@ -2080,8 +2080,11 @@ read-extended-command--affixation
>> (obsolete
>> (format " (%s)" (car obsolete)))
>> ((and binding (not (stringp binding)))
>> - (format " (%s)" (key-description binding))))))
>> - (if suffix (list command-name suffix) command-name)))
>> + (format " (%s)" (key-description binding)))
>> + (t ""))))
>> + (put-text-property 0 (length suffix)
>> + 'face 'completions-annotations suffix)
>> + (list command-name "" suffix)))
>> command-names)))
>
> Why such change only for one particular use of annotations?
> Shouldn't completion--insert-strings check if the suffix is an
> empty string, and then put the 'completions-annotations' face on it?
I did not do this since I wanted to avoid magic which complicates the
definition of the `affixation-function`. The idea was to never add faces
to the annotations supplied by the `affixation-function`.
I am looking at the `affixation-function` from the perspective of how
the definition can be made as simple/predicatable as possible for the
API user since there are other completion UIs and many completion tables
which will make use of this. I treat the completion UI behind the API as
a blackbox.
In contrast you take the perspective of how the affixation function
could be fitted best into the existing completion code without
introducing artificial restrictions.
I argue that it is better to take a step back from the actual code base
in minibuffer.el and adopt the simpler definition.
Daniel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] `affixation-function`: Allow only three-element lists
2021-04-25 18:02 ` Daniel Mendler
@ 2021-04-25 20:34 ` Juri Linkov
2021-04-25 21:04 ` Daniel Mendler
0 siblings, 1 reply; 7+ messages in thread
From: Juri Linkov @ 2021-04-25 20:34 UTC (permalink / raw)
To: Daniel Mendler; +Cc: Stefan Monnier, emacs-devel
>>> + (cl-assert (or (not completions)
>>> + (= 3 (length (car completions))))))
> I am looking at the `affixation-function` from the perspective of how the
> definition can be made as simple/predicatable as possible for the API user
> since there are other completion UIs and many completion tables which will
> make use of this. I treat the completion UI behind the API as a blackbox.
I completely agree that for `affixation-function` part of
the API is would be cleaner to document the input data as
only candidate + prefix + suffix.
But I don't agree with `cl-assert`. It looks too odd.
Why to validate that the length of the first candidate is 3?
Why not to validate than the length of every candidate
is not more than 3? Why not to validate that there are no nils
in the list? Why not to validate there are only strings? Etc.
IOW, I think it's responsibility of the API user to provide valid data
as documented.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] `affixation-function`: Allow only three-element lists
2021-04-25 20:34 ` Juri Linkov
@ 2021-04-25 21:04 ` Daniel Mendler
2021-04-27 16:45 ` Juri Linkov
0 siblings, 1 reply; 7+ messages in thread
From: Daniel Mendler @ 2021-04-25 21:04 UTC (permalink / raw)
To: Juri Linkov; +Cc: Stefan Monnier, emacs-devel
On 4/25/21 10:34 PM, Juri Linkov wrote:
> I completely agree that for `affixation-function` part of
> the API is would be cleaner to document the input data as
> only candidate + prefix + suffix.
>
> But I don't agree with `cl-assert`. It looks too odd.
> Why to validate that the length of the first candidate is 3?
> Why not to validate than the length of every candidate
> is not more than 3? Why not to validate that there are no nils
> in the list? Why not to validate there are only strings? Etc.
Okay, fair enough. I am fine if the `cl-assert` is removed from the
patch. The other changes should be kept though, such that we do not
violate the more restricted specification. Other completion UIs may not
support the two-element affixations which are then still accidentally
allowed by the default completion UI. The `cl-assert` is just a cheap
check to ensure that no violating affixation functions are accidentally
reintroduced. But you are right that this is not fail-safe. Do you want
me to send an updated patch with the `cl-assert` removed?
Daniel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] `affixation-function`: Allow only three-element lists
2021-04-25 21:04 ` Daniel Mendler
@ 2021-04-27 16:45 ` Juri Linkov
2021-04-27 17:40 ` Daniel Mendler
0 siblings, 1 reply; 7+ messages in thread
From: Juri Linkov @ 2021-04-27 16:45 UTC (permalink / raw)
To: Daniel Mendler; +Cc: Stefan Monnier, emacs-devel
> Okay, fair enough. I am fine if the `cl-assert` is removed from the
> patch. The other changes should be kept though, such that we do not violate
> the more restricted specification. Other completion UIs may not support the
> two-element affixations which are then still accidentally allowed by the
> default completion UI. The `cl-assert` is just a cheap check to ensure that
> no violating affixation functions are accidentally reintroduced. But you
> are right that this is not fail-safe. Do you want me to send an updated
> patch with the `cl-assert` removed?
Your already sent patch is fine, thanks. I only removed `cl-assert`,
added a fix in the Info node "Programmed Completion", and pushed to master.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-04-27 17:40 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-04-25 0:39 [PATCH] `affixation-function`: Allow only three-element lists Daniel Mendler
2021-04-25 17:46 ` Juri Linkov
2021-04-25 18:02 ` Daniel Mendler
2021-04-25 20:34 ` Juri Linkov
2021-04-25 21:04 ` Daniel Mendler
2021-04-27 16:45 ` Juri Linkov
2021-04-27 17:40 ` Daniel Mendler
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).