Skip to content

Commit

Permalink
Fix completions when using flex-like completion styles (#3659)
Browse files Browse the repository at this point in the history
  • Loading branch information
toniz4 authored May 21, 2024
1 parent b37a8d5 commit 167634a
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 46 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

### Bugs fixed

- [#3659](https://github.com/clojure-emacs/cider/pull/3659): Fixes completions when using `flex`-like completion styles.
- [#3600](https://github.com/clojure-emacs/cider/pull/3600): Fix scittle jack-in when using `cider-jack-in-clj`.
- [#3663](https://github.com/clojure-emacs/cider/issues/3663): Fix `cider-interactive-eval-override` invocation.

Expand Down
32 changes: 18 additions & 14 deletions cider-completion.el
Original file line number Diff line number Diff line change
Expand Up @@ -181,16 +181,25 @@ performed by `cider-annotate-completion-function'."

(defun cider-complete-at-point ()
"Complete the symbol at point."
(when-let* ((bounds (bounds-of-thing-at-point 'symbol)))
(when-let* ((bounds (or (bounds-of-thing-at-point 'symbol)
(cons (point) (point))))
(bounds-string (buffer-substring (car bounds) (cdr bounds))))
(when (and (cider-connected-p)
(not (or (cider-in-string-p) (cider-in-comment-p))))
(let* (last-prefix
(let* (last-bounds-string
last-result
(complete
(lambda (prefix)
(unless (string-equal last-prefix prefix)
(setq last-prefix prefix)
(setq last-result (cider-complete prefix)))
(lambda ()
;; We are Not using the prefix extracted within the (prefix pred action)
;; lambda. In certain completion styles, the prefix might be an empty
;; string, which is unreliable. A more dependable method is to use the
;; string defined by the bounds of the symbol at point.
;;
;; Caching just within the function is sufficient. Keeping it local
;; ensures that it will not extend across different CIDER sessions.
(unless (string= bounds-string last-bounds-string)
(setq last-bounds-string bounds-string)
(setq last-result (cider-complete bounds-string)))
last-result)))
(list (car bounds) (cdr bounds)
(lambda (prefix pred action)
Expand All @@ -205,8 +214,7 @@ performed by `cider-annotate-completion-function'."
(cond ((eq action 'metadata) `(metadata (category . cider))) ;; defines a completion category named 'cider, used later in our `completion-category-overrides` logic.
((eq (car-safe action) 'boundaries) nil)
(t (with-current-buffer (current-buffer)
(complete-with-action action
(funcall complete prefix) prefix pred)))))
(complete-with-action action (funcall complete) prefix pred)))))
:annotation-function #'cider-annotate-symbol
:company-kind #'cider-company-symbol-kind
:company-doc-buffer #'cider-create-compact-doc-buffer
Expand Down Expand Up @@ -264,12 +272,6 @@ in the buffer."
cider-company-unfiltered-candidates
"CIDER backend-driven completion style."))

;; Currently CIDER completions only work for `basic`, and not `initials`, `partial-completion`, `orderless`, etc.
;; So we ensure that those other styles aren't used with CIDER, otherwise one would see bad or no completions at all.
;; This `add-to-list` call can be removed once we implement the other completion styles.
;; (When doing that, please refactor `cider-enable-flex-completion' as well)
(add-to-list 'completion-category-overrides '(cider (styles basic)))

(defun cider-company-enable-fuzzy-completion ()
"Enable backend-driven fuzzy completion in the current buffer.
Expand All @@ -292,6 +294,8 @@ Only affects the `cider' completion category.`"
(setq completion-category-overrides (seq-remove (lambda (x)
(equal 'cider (car x)))
completion-category-overrides))
(unless found-styles
(setq found-styles '(styles basic)))
(unless (member 'flex found-styles)
(setq found-styles (append found-styles '(flex))))
(add-to-list 'completion-category-overrides (apply #'list 'cider found-styles (when found-cycle
Expand Down
54 changes: 26 additions & 28 deletions doc/modules/ROOT/pages/usage/code_completion.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,27 @@ is already properly indented.

== Completion styles

CIDER defines (via the `completion-styles-alist` Elisp variable) a completion category named `cider`.
CIDER defines a specialized completion category through the `cider-complete-at-point` function,
added to `completion-at-point-functions`, establishing a dedicated 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).
The CIDER completion at point function supports most completion styles, including
`partial-completion`, `orderless` and `flex` (read more below).

CIDER declares so in this fashion:

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-overrides`, overwriting the completion style of the CIDER
complete at point function. The following snippet accomplishes that:

[source,lisp]
----
(add-to-list 'completion-category-overrides '(cider (styles basic)))
----

This specifies that the `cider` completion category should employ the basic completion style by
default.

You can also enable the `flex` completion style by activating xref:usage/code_completion.adoc#fuzzy-candidate-matching[fuzzy candidate matching].

== Auto-completion
Expand Down Expand Up @@ -131,13 +140,14 @@ without needing to hit an extra key, please customize:

=== 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:
By default, CIDER will use the completion styles defined in
`completion-styles`, the defaults being `(basic partial-completion
emacs22)` since Emacs 23. For a better description of how those
completion styles operates, refer to the official Emacs manual on
https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion-Styles.html[how completion alternatives are chosen].

CIDER provides a function to enable the `flex` completion style for CIDER-specific
completions. If you wish to enable that, you can add this to your config:

[source,lisp]
----
Expand All @@ -146,11 +156,11 @@ CIDER-specific "fuzzy completion" by setting up in your Emacs init file:

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
Now, `company-mode` (and other completion packages like `corfu`) 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
https://github.com/alexander-yakushev/compliment/wiki/Examples[here].

NOTE: `cider-company-enable-fuzzy-completion` (now deprecated) should be used for Emacs < 27.
Expand Down Expand Up @@ -189,18 +199,6 @@ keys to cancel the prompt by customizing:
(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:

[source,lisp]
----
(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
Expand Down
22 changes: 18 additions & 4 deletions test/cider-completion-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,29 @@
(let ((old-value completion-category-overrides))
(unwind-protect
(progn
(it "adds `flex'"
(cider-enable-flex-completion)
(expect (member 'flex (assq 'styles (assq 'cider completion-category-overrides)))
:to-be-truthy))
(it "adds `flex' and `basic' as a fallback"
(let ((expected-category-overrides '((cider (styles basic flex)))))
(cider-enable-flex-completion)
(expect (member 'flex (assq 'styles (assq 'cider completion-category-overrides)))
:to-be-truthy)
(expect (member 'basic (assq 'styles (assq 'cider completion-category-overrides)))
:to-be-truthy)
(expect completion-category-overrides :to-equal expected-category-overrides)))

(it "doesn't add `cycle'"
(expect (assq 'cycle (assq 'cider completion-category-overrides))
:to-be nil))

(it "adds just `flex' if there is another style present"
(setq completion-category-overrides '((cider (styles partial-completion))))
(cider-enable-flex-completion)
(expect (member 'flex (assq 'styles (assq 'cider completion-category-overrides)))
:to-be-truthy)
(expect (member 'partial-completion (assq 'styles (assq 'cider completion-category-overrides)))
:to-be-truthy)
(expect (member 'basic (assq 'styles (assq 'cider completion-category-overrides)))
:to-be nil))

(it "doesn't re-add `flex' if already present, preserving `cycle' as well"
(let ((with-flex-and-cycle '((cider (styles basic flex)
(cycle t)))))
Expand Down

0 comments on commit 167634a

Please sign in to comment.