]> git.eshelyaron.com Git - emacs.git/commitdiff
(minibuffer-completion-help): Add group sorting
authorDaniel Mendler <mail@daniel-mendler.de>
Tue, 11 May 2021 07:08:05 +0000 (09:08 +0200)
committerJuri Linkov <juri@linkov.net>
Thu, 20 May 2021 17:50:35 +0000 (20:50 +0300)
Sort the groups as returned by the `group-function` of the completion
table depending on the value of the customizable variable
`completions-group-sort`.  By default `completions-group-sort` is set
to nil.  The variable can be set to the symbol `alphabetical` in order
to configure alphabetical sorting.  Furthermore, a custom sorting
function can be used as value of `completions-group-sort`.

* lisp/minibuffer.el (completions-group-sort): New variable.
(minibuffer--group-by): Add SORT-FUN argument.
(minibuffer-completion-help): Pass `completions-group-sort` to
`minibuffer--group-by`.

lisp/minibuffer.el

index 35ae4b8bcb1bfc26ca1de8f44b3b2bda81f96abe..e04f1040b38ea63e3b18b6021716674bbf5b28ca 100644 (file)
@@ -1147,10 +1147,22 @@ completion candidates than this number."
 
 (defcustom completions-group nil
   "Enable grouping of completion candidates in the *Completions* buffer.
-See also `completions-group-format'."
+See also `completions-group-format' and `completions-group-sort'."
   :type 'boolean
   :version "28.1")
 
+(defcustom completions-group-sort nil
+  "Sort groups in the *Completions* buffer.
+
+The value can either be nil to disable sorting, `alphabetical' for
+alphabetical sorting or a custom sorting function.  The sorting
+function takes and returns an alist of groups, where each element is a
+pair of a group title string and a list of group candidate strings."
+  :type '(choice (const :tag "No sorting" nil)
+                 (const :tag "Alphabetical sorting" alphabetical)
+                 function)
+  :version "28.1")
+
 (defcustom completions-group-format
   (concat
    (propertize "    " 'face 'completions-group-separator)
@@ -1434,16 +1446,21 @@ Remove completion BASE prefix string from history elements."
                      (substring c base-size)))
                  hist)))))
 
-(defun minibuffer--group-by (fun elems)
-  "Group ELEMS by FUN."
+(defun minibuffer--group-by (group-fun sort-fun elems)
+  "Group ELEMS by GROUP-FUN and sort groups by SORT-FUN."
   (let ((groups))
     (dolist (cand elems)
-      (let* ((key (funcall fun cand nil))
+      (let* ((key (funcall group-fun cand nil))
              (group (assoc key groups)))
         (if group
             (setcdr group (cons cand (cdr group)))
           (push (list key cand) groups))))
-    (mapcan (lambda (x) (nreverse (cdr x))) (nreverse groups))))
+    (setq groups (nreverse groups)
+          groups (mapc (lambda (x)
+                         (setcdr x (nreverse (cdr x))))
+                       groups)
+          groups (funcall sort-fun groups))
+    (mapcan #'cdr groups)))
 
 (defun completion-all-sorted-completions (&optional start end)
   (or completion-all-sorted-completions
@@ -2216,7 +2233,17 @@ variables.")
                       ;; `group-function'.
                       (when group-fun
                         (setq completions
-                              (minibuffer--group-by group-fun completions)))
+                              (minibuffer--group-by
+                               group-fun
+                               (pcase completions-group-sort
+                                 ('nil #'identity)
+                                 ('alphabetical
+                                  (lambda (groups)
+                                    (sort groups
+                                          (lambda (x y)
+                                            (string< (car x) (car y))))))
+                                 (_ completions-group-sort))
+                               completions)))
 
                       (cond
                        (aff-fun