summaryrefslogtreecommitdiff
path: root/lisp/minibuffer.el
diff options
context:
space:
mode:
authorDaniel Mendler <mail@daniel-mendler.de>2021-04-19 22:13:55 +0200
committerStefan Monnier <monnier@iro.umontreal.ca>2021-04-19 18:05:36 -0400
commit296ef2e99b7cd83ad236230ddc941c7dbc8766e6 (patch)
treef9a23887145601bf5d9eb69ee6c47710e3260105 /lisp/minibuffer.el
parent9216e1818a6f8dd33f98d435fc4927f6dd361d5c (diff)
downloademacs-296ef2e99b7cd83ad236230ddc941c7dbc8766e6.tar.gz
emacs-296ef2e99b7cd83ad236230ddc941c7dbc8766e6.tar.bz2
emacs-296ef2e99b7cd83ad236230ddc941c7dbc8766e6.zip
(completion-all-sorted-completions): Additional alphabetical sorting
Even in the cases where it does not make much visible difference, it brings the benefit of making the result deterministic. * minibuffer.el (minibuffer--sort-by-length-alpha): New function. (minibuffer--sort-by-position): New function extracted from `completion-all-sorted-completions`. (completion-all-sorted-completions): Use use them.
Diffstat (limited to 'lisp/minibuffer.el')
-rw-r--r--lisp/minibuffer.el49
1 files changed, 30 insertions, 19 deletions
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index c19f9096290..4ed596430c6 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1362,6 +1362,25 @@ KEYFUN takes an element of ELEMS and should return a numerical value."
(sort (mapcar (lambda (x) (cons (funcall keyfun x) x)) elems)
#'car-less-than-car)))
+(defun minibuffer--sort-by-position (hist elems)
+ "Sort ELEMS by their position in HIST."
+ (let ((hash (make-hash-table :test #'equal :size (length hist)))
+ (index 0))
+ ;; Record positions in hash
+ (dolist (c hist)
+ (unless (gethash c hash)
+ (puthash c index hash))
+ (cl-incf index))
+ (minibuffer--sort-by-key
+ elems (lambda (x) (gethash x hash most-positive-fixnum)))))
+
+(defun minibuffer--sort-by-length-alpha (elems)
+ "Sort ELEMS first by length, then alphabetically."
+ (sort elems (lambda (c1 c2)
+ (or (< (length c1) (length c2))
+ (and (= (length c1) (length c2))
+ (string< c1 c2))))))
+
(defun completion-all-sorted-completions (&optional start end)
(or completion-all-sorted-completions
(let* ((start (or start (minibuffer-prompt-end)))
@@ -1395,25 +1414,17 @@ KEYFUN takes an element of ELEMS and should return a numerical value."
(sort-fun
(setq all (funcall sort-fun all)))
(t
- ;; Prefer shorter completions, by default.
- (setq all (sort all (lambda (c1 c2) (< (length c1) (length c2)))))
- (if (and (minibufferp) (not (eq minibuffer-history-variable t)))
- ;; Prefer recently used completions and put the default, if
- ;; it exists, on top.
- (let* ((hist (symbol-value minibuffer-history-variable))
- (hash (make-hash-table :test #'equal :size (length hist)))
- (index 0)
- (def (car-safe minibuffer-default)))
- ;; Record history positions in hash
- (dolist (c hist)
- (unless (gethash c hash)
- (puthash c index hash))
- (cl-incf index))
- (when (stringp def)
- (puthash def -1 hash))
- (setq all (minibuffer--sort-by-key
- all (lambda (x)
- (gethash x hash most-positive-fixnum))))))))
+ ;; Sort first by length and alphabetically.
+ (setq all (minibuffer--sort-by-length-alpha all))
+
+ ;; Sort by history position, put the default, if it
+ ;; exists, on top.
+ (when (and (minibufferp) (not (eq minibuffer-history-variable t)))
+ (let ((def (car-safe minibuffer-default))
+ (hist (symbol-value minibuffer-history-variable)))
+ (setq all (minibuffer--sort-by-position
+ (if def (cons def hist) hist)
+ all))))))
;; Cache the result. This is not just for speed, but also so that
;; repeated calls to minibuffer-force-complete can cycle through