Subject: Re: bug#41706: 26.1; sort-subr predicate cannot be set successfully

From: Michael Heerdegen <[email-masked]>
Date: Thu, 11 Jun 2020 14:55:14 +0200

Eli Zaretskii <[email-masked]> writes:

> That's a beginning, thanks.  But it needs more work, IMO:
>
>  . the cons cell case hints on a possible return value of STARTKEYFUN,
>    AFAIU, but the text doesn't say so
>  . the case of STARTKEYFUN being nil is another use case for what
>    PREDICATE must cope with, and the text should say so
>  . the text about ENDKEYFUN should also be augmented, IMO
>  . the description of PREDICATE should reference this text in some
>    useful way

I must admit I found the doc sufficient for all of these.  Actually,
reading the implementation might be simpler than describing it:

#+begin_src emacs-lisp
(setq key (catch 'key
		  (or (and startkeyfun (funcall startkeyfun))
		      ;; If key was not returned as value,
		      ;; move to end of key and get key from the buffer.
		      (let ((start (point)))
			(funcall (or endkeyfun
				     (prog1 endrecfun (setq done t))))
			(cons start (point))))))
#+end_src

What the doc is missing to mention is the `catch' - `sort-regexp-fields'
uses this feature for example.

Here is an attempt (not including the `catch' feature), anyway:

diff --git a/lisp/sort.el b/lisp/sort.el
index de0e1b9519..e22f062dbd 100644
--- a/lisp/sort.el
+++ b/lisp/sort.el
@@ -80,7 +80,15 @@ sort-subr
 PREDICATE, if non-nil, is the predicate function for comparing
 keys; it is called with two arguments, the keys to compare, and
 should return non-nil if the first key should sort before the
-second key.  If PREDICATE is nil, comparison is done with `<' if
+second key.  The key values PREDICATE is called with are the
+either the return values of STARTKEYFUN when that function is
+specified and returns a non-nil value.  In any other case the keys
+are cons cells of the form (BEG . END), where BEG is the value of
+point after calling STARTKEYFUN when given, else after calling
+ENDRECFUN, and END is the value of point after calling ENDKEYFUN when
+given, and after calling ENDRECFUN else.
+
+If PREDICATE is nil, comparison is done with `<' if
 the keys are numbers, with `compare-buffer-substrings' if the
 keys are cons cells (the car and cdr of each cons cell are taken
 as start and end positions), and with `string<' otherwise."

What I also would like to add to the docstring of this function, and of
that of `sort', is that the PREDICATE must be transitive and
antisymmetric - mentioning only in the manual is not enough IMHO.

> > BTW, what about the suggestion to support collation order out of the
> > box?
>
> What collation would you like to support, and in what form?

I don't know much about this stuff.  The canonical way from my ignorant
point of view would be that `compare-buffer-substrings' would not only
respect `case-fold-search' but also some other variable which would tell
how the behavior should be w.r.t. collation.

Michael.