11

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?

11

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 Apr 5 '20 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. 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.

1
  • This doesn't work for me in Emacs 27. – Adam Simpson Dec 7 '18 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 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.)

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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