Emacs: mct version 1.1.0

Opinionated changes and enhancements to the default minibuffer completion UI of Emacs:

  • Live completions to update the results as you type.

  • Passlist and blocklist of commands or completion categories to control whether the *Completions* buffer shows up eagerly.

  • Other relevant options to control when the *Completions* are displayed.

  • Per command or completion category sorting methods.

  • A cleaner *Completions* buffer, optionally without a mode line.

  • Commands to cycle from the minibuffer to the *Completions* and vice versa.

In essence, MCT is (i) a layer of interactivity on top of the out-of-the-box completion experience, and (ii) glue code that combines built-in functionalities to make the default completion framework work like that of more featureful third-party options.

Below are the release notes.


Version 1.1.0 on 2025-07-07

This version contains several refinements to an already stable package.

Sort by command or completion category

The new user option mct-sort-by-command-or-category determines how completion candidates are sorted.

This is an alist where each element is of the form (SYMBOLS . SORT-FUNCTION).

SYMBOLS is either a symbol or a list of symbols. SYMBOLS can refer to the symbol of a function or completion category. It can also be t, which refers to the fallback value.

SORT-FUNCTION is a function that takes a list of strings and returns a list of strings, sorting them accordingly. Examples of a SORT-FUNCTION are:

  • mct-sort-by-alpha
  • mct-sort-by-alpha-then-by-length
  • mct-sort-by-history
  • mct-sort-by-directory-then-by-file

To not perform any sorting on the completion candidates that match SYMBOLS set SORT-FUNCTION to nil.

If there are conflicting configurations between a SYMBOLS function and completion category, then the function takes precedence (for example find-file is set to sort directories first whereas the file completion category is set to sort by history).

Optional indicator for completing-read-multiple

Users of Emacs prior to version 31 do not have a built-in way to inform them when they are dealing with a completing-read-multiple minibuffer prompt. Emacs 31 introduces the user option crm-prompt and its related functionality to tell the user what they need to know.

The mct-completing-read-multiple-indicator can be used in the meantime to achieve the same results. It is set to a non-nil value by default. Opt out by changing it to nil.

The *Completions* are persistent when needed

This concerns the case where a command or completion category is part of the mct-completion-passlist or when the user option mct-live-completion is set to non-nil or visible. In such cases, the completion candidates are on display and we want to keep them there while performing a dynamic completion, such as with the find-file command (“dynamic” in the sense that it returns a new list of candidates to match the current path).

Persisting the *Completions* means that as we narrow the list, we still see all the matching results.

In the past, we provided the option mct-persist-dynamic-completion though we do not need it anymore.

I was inspired to make this change in response to a question posed by Ryan Davis regarding the behaviour of mct-persist-dynamic-completion. This was done in issue 7: https://github.com/protesilaos/mct/issues/7.

Miscellaneous

  • Vertical alignment of the *Completions* buffer is more precise. Thanks to Jessie Hu for the contribution in pull request 6: https://github.com/protesilaos/mct/pull/6.

  • The command mct-choose-completion-exit no longer tries to expand further. In the previous implementation it would try to match the last known selection from the history when using a file prompt. For example we have this workflow:

    • In the previous prompt we type /path/to/file/ and exit.
    • Now we type /pa, the completions pop up, we select /path and invoke mct-choose-completion-exit. This wrongly expands into /path/foo/ instead of taking just /path (given that it has no further input to determine an extension of that string).

    Now the command will do the right thing based on the user’s input.