Code Completion

CIDER provides intelligent code completion for both source buffers (powered by cider-mode) and REPL buffers.

Internally CIDER leverages compliment for Clojure and clj-suitable for ClojureScript.

Improvements to the two libraries automatically translate to improvements in CIDER.

Standard completion

Out-of-the box CIDER uses the standard Emacs tooling for code completion. When you press TAB or M-TAB you’ll get completion candidates in a dedicated buffer.

Code Completion

There are two things to keep in mind about the standard completion:

  1. The default keybinding M-TAB is not usable in desktop environments that use it for switching between open applications.

  2. You have to configure TAB to do completion manually by adding this snippet your Emacs config:

(setq tab-always-indent 'complete)

Normally TAB only indents, but now it will also do completion if the code is already properly indented.

Completion styles

CIDER defines (via the completion-styles-alist Elisp variable) a completion category named cider.

The cider completion category currently only supports basic completion styles (and not partial-completion, orderless, etc), and flex, optionally (read more below).

CIDER declares so in this fashion:

(add-to-list 'completion-category-overrides '(cider (styles basic)))

You can also enable the flex completion style by activating fuzzy candidate matching.

Auto-completion

While the standard Emacs tooling works just fine, we suggest that CIDER users consider using company-mode or corfu-mode instead. These can be used for auto-completion in both source code and REPL buffers, with the following advantages:

  • A nicer UI.

  • Integration with Clojure docstrings and Java doc comments.

Configuration

Both company-mode and corfu-mode are affected by the following CIDER configuration options:

  • cider-docstring-max-lines (default 20) controls how many lines, at most, of this docstring will be included (in a popup or the echo area, depending on your setup) while offering completions. It’s worth noting, for Java documentation, CIDER doesn’t simply trim lines, but it looks at the structure and tries to find the largest combination of these that fits into cider-docstring-max-lines:

    • The entire comment body, followed by its "block tags" (Returns/Throws/Params information)

    • The first sentence of the comment, followed by the block tags

    • The block tags

    • The first sentence of the comment.

company-mode installation

To install company-mode:

M-x package-install RET company RET

After installation, you can turn on company-mode globally:

(global-company-mode)

or through mode-specific hooks:

(add-hook 'cider-repl-mode-hook #'company-mode)
(add-hook 'cider-mode-hook #'company-mode)

When company-mode is enabled, it will receive completion information from cider-complete-at-point and requires no additional setup or plugins.

If you’d prefer to trigger completions manually you can add this to your config:

(setq company-idle-delay nil) ; never start completions automatically
(global-set-key (kbd "M-TAB") #'company-complete) ; use M-TAB, a.k.a. C-M-i, as manual trigger

To make TAB complete, without losing the ability to manually indent, you can add this to your config:

(global-set-key (kbd "TAB") #'company-indent-or-complete-common)

Company’s documentation mechanism and CIDER’s documentation facilities are integrated.

While a completion is being offered to you, you can hit (F1) (the default company-show-doc-buffer key binding) for displaying documentation and arglists under a temporary cider-doc buffer.

In order for Company to always show docstrings and other metadata under a temporary cider-doc buffer, without needing to hit an extra key, please customize:

;; (You may want to do this as a setq-local within a clojure-mode-hook instead)
(custom-set-variables '(company-auto-update-doc t))

Fuzzy candidate matching

By default, CIDER will provide completion candidates with the assumption that whatever you’ve typed so far is a prefix of what you’re really trying to type. For example, if you type map- then you’ll only get completion candidates that have map- as the beginning of their names. Sometimes, you don’t know the exact prefix for the item you want to type. In this case, you can get CIDER-specific "fuzzy completion" by setting up in your Emacs init file:

(cider-enable-flex-completion)

This adds the flex completion style, as introduced in Emacs 27.

Now, company-mode will accept certain fuzziness when matching candidates against the prefix. For example, typing mi will show you map-indexed as one of the possible completion candidates and cji will complete to clojure.java.io. Different completion examples are shown here.

cider-company-enable-fuzzy-completion (now deprecated) should be used for Emacs < 27.

Completion annotations

Completion candidates will be annotated by default with an abbreviation corresponding to their type, and (contextually) their namespace. The function used to format the annotation can be configured by cider-annotate-completion-function. The abbreviations used are configured by cider-completion-annotations-alist and the context in which their namespace is included is configured by cider-completion-annotations-include-ns.

Completion Annotations
Completion annotations can be disabled by setting cider-annotate-completion-candidates to nil.

Notes on class disambiguation

Sometimes, the completion user experience may be interrupted by a completing-read that asks for the Member in class. This is used for better Java completions and documentation.

However, if you are not interested in the current candidate, disambiguating it is of no use, and the prompt can be a nuisance.

If you are using Company for completions and IDO for completing-read, you can cause the <up> and <down> keys to cancel the prompt by customizing:

(advice-add 'cider-class-choice-completing-read
            :around
            (lambda (f a b)
              (cider--with-temporary-ido-keys "<up>" "<down>"
                (funcall f a b))))

Changing the completion style

Sometimes the user may want to use a different completion style just for the CIDER complete at point function. That can be achieved by setting completion-category-defaults, overriting the completion style of the CIDER complete at point function. The following snippet accomplishes that:

(add-to-list 'completion-category-defaults '(cider (styles basic)))

Updating stale classes and methods cache

Sometimes, the completion fails to recognize new classes that came with dependencies that were loaded dynamically after the REPL was started (e.g. via Boot). Executing M-x cider-completion-flush-caches (or going through the menu CIDER Interaction->Misc->Flush completion cache) forces the completion backend to re-read all classes it can find on the classpath.

Implementation Details

You don’t really need to know any of this if you’re using only cider-jack-in.

The bulk of the code completion logic resides in cider-nrepl completion middleware. Internally it delegates to compliment for the Clojure completion and clj-suitable for the ClojureScript completion.

Starting with nREPL 0.8, there’s also a built-in completions nREPL op that CIDER will fallback to, in the absence of cider-nrepl. Its API is similar to that of the complete op in cider-nrepl and it can be configured to use different completion functions. The built-in op currently supports only Clojure. See the nREPL docs for more details.

Basically, you’ll get great code completion in the presence of cider-nrepl and basic completion otherwise.