12

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?

NickD
  • 27,023
  • 3
  • 23
  • 42
Tu Do
  • 6,772
  • 20
  • 39
  • https://emacs.stackexchange.com/tags/elisp/info - the `elisp` tag has a specific meaning and it should be used *very rarely*. – NickD Mar 11 '23 at 03:35

4 Answers4

14

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. ]

Stefan
  • 26,154
  • 3
  • 46
  • 84
  • 1
    If you want `icomplete` to also respect the order, you can add a `(cycle-sort-function . ,#'identity)` to the metadata list. – Omar Apr 05 '20 at 00:35
  • I needed to use `reverse` instead of `identity` to display the list in the original order! Why? (24.3.1) – John H. Sep 11 '20 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 Sep 11 '20 at 16:09
2

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.

Dan
  • 32,584
  • 6
  • 98
  • 168
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"))))
abo-abo
  • 13,943
  • 1
  • 29
  • 43
  • 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 Feb 10 '15 at 15:32
  • That's a lame reason not to use it. Just postprocess whatever `semantic-format-tag-summarize` gives you. – abo-abo Feb 10 '15 at 15:36
  • Or submit a bug report for `ido` – abo-abo Feb 10 '15 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 Feb 10 '15 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 Feb 10 '15 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.)

Drew
  • 75,699
  • 9
  • 109
  • 225
  • 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 Feb 10 '15 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 Feb 10 '15 at 16:58