13

Either:

(completing-read "test: " '("a" "b" "c"))

or:

(completing-read "test: " '("c" "b" "a"))

produces the same result in completion buffer when pressing TAB. How do I make it respect the sorting order?

1

4 Answers 4

15

The sorting order in the *Completions* list is determined by the display-sort-function property of your completion table (as returned by completion-metadata). In your case, your completion table has no such property, so it falls back to the default, which is to sort alphabetically.

You can use:

(defun my-presorted-completion-table (completions)
  (lambda (string pred action)
    (if (eq action 'metadata)
        `(metadata (display-sort-function . ,#'identity))
      (complete-with-action action completions string pred))))

and then

(completing-read "test: " (my-presorted-completion-table '("a" "b" "c")))

[ This assumes you're using lexical-binding. ]

3
  • 1
    If you want icomplete to also respect the order, you can add a (cycle-sort-function . ,#'identity) to the metadata list.
    – Omar
    Commented Apr 5, 2020 at 0:35
  • I needed to use reverse instead of identity to display the list in the original order! Why? (24.3.1)
    – John H.
    Commented Sep 11, 2020 at 15:19
  • @JohnH.: Sounds like a bug (in 24.3). If you can reproduce the problem in Emacs-27, you might want to report it as a bug.
    – Stefan
    Commented Sep 11, 2020 at 16:09
3

Give completing-read a list of lists, and it will respect the order:

(completing-read "test: " '(("a") ("b") ("c")))
(completing-read "test: " '(("c") ("b") ("a")))

The docstring says:

(completing-read PROMPT COLLECTION &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)

Read a string in the minibuffer, with completion. PROMPT is a string to prompt with; normally it ends in a colon and a space. COLLECTION can be a list of strings, an alist, an obarray or a hash table. ...

It can therefore take an alist as a collection. In effect, you're creating an alist with keys but without values.

1
  • This doesn't work for me in Emacs 27. Commented Dec 7, 2018 at 19:27
2

I'd suggest not using this ancient spell.

The built-in ido-completing-read doesn't have this deficiency:

(ido-completing-read "test: " '("a" "b" "c"))
(ido-completing-read "test: " '("c" "b" "a"))

Neither does helm:

(helm :sources
      `((name . "test: ")
        (candidates . ("a" "b" "c"))))
(helm :sources
      `((name . "test: ")
        (candidates . ("c" "b" "a"))))
5
  • 1
    The problem with ido-completing-read is that it has weird newline character ^ from semantic-format-tag-summarize. As for Helm, I cannot assume everyone use it. That's why completing-read is the only option.
    – Tu Do
    Commented Feb 10, 2015 at 15:32
  • That's a lame reason not to use it. Just postprocess whatever semantic-format-tag-summarize gives you.
    – abo-abo
    Commented Feb 10, 2015 at 15:36
  • Or submit a bug report for ido
    – abo-abo
    Commented Feb 10, 2015 at 15:36
  • 1
    I did that as well but did not succeed. The output from semantic-format-tag-summarize returns something at the end, but the character is not displayed in completing-read or helm-comp-read. I already wrote another function in place of semantic-format-tag-summarize, without face yet. For displaying tags (with colors) to users, I still use semantic-format-tag-summarize but use a custom buffer with text widgets instead.
    – Tu Do
    Commented Feb 10, 2015 at 16:20
  • Probably I will submit bug to Ido after finding out what semantic-format-tag-summarize returns at the end. I had a solution but I still want to know a solution to completing-read. I know Helm can make it but just wanted to know if an easy way with completing-read exists.
    – Tu Do
    Commented Feb 10, 2015 at 16:22
1

If you use Icicles then the order is respected by completing-read.

(And you can sort using different sort orders, either interactively or via Lisp. And unlike vanilla Emacs, sorting affects both *Completions* display and cycling order.)

2
  • 1
    Same as the comment in abo-abo's answer, I cannot rely on external packages. And ido-completing-read is having some problem.
    – Tu Do
    Commented Feb 10, 2015 at 15:33
  • 2
    Perhaps you cannot, but perhaps someone else can. ;-) This is a simple solution to the problem as posed: just use completing-read with Icicles. You can even just turn on icicle-mode temporarily (e.g. for the call to completing-read), using, e.g., macro icicle-with-icy-mode-ON.
    – Drew
    Commented Feb 10, 2015 at 16:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.