Skip to content

Commit 167634a

Browse files
authored
Fix completions when using flex-like completion styles (#3659)
1 parent b37a8d5 commit 167634a

File tree

4 files changed

+63
-46
lines changed

4 files changed

+63
-46
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
### Bugs fixed
3737

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

cider-completion.el

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,25 @@ performed by `cider-annotate-completion-function'."
181181

182182
(defun cider-complete-at-point ()
183183
"Complete the symbol at point."
184-
(when-let* ((bounds (bounds-of-thing-at-point 'symbol)))
184+
(when-let* ((bounds (or (bounds-of-thing-at-point 'symbol)
185+
(cons (point) (point))))
186+
(bounds-string (buffer-substring (car bounds) (cdr bounds))))
185187
(when (and (cider-connected-p)
186188
(not (or (cider-in-string-p) (cider-in-comment-p))))
187-
(let* (last-prefix
189+
(let* (last-bounds-string
188190
last-result
189191
(complete
190-
(lambda (prefix)
191-
(unless (string-equal last-prefix prefix)
192-
(setq last-prefix prefix)
193-
(setq last-result (cider-complete prefix)))
192+
(lambda ()
193+
;; We are Not using the prefix extracted within the (prefix pred action)
194+
;; lambda. In certain completion styles, the prefix might be an empty
195+
;; string, which is unreliable. A more dependable method is to use the
196+
;; string defined by the bounds of the symbol at point.
197+
;;
198+
;; Caching just within the function is sufficient. Keeping it local
199+
;; ensures that it will not extend across different CIDER sessions.
200+
(unless (string= bounds-string last-bounds-string)
201+
(setq last-bounds-string bounds-string)
202+
(setq last-result (cider-complete bounds-string)))
194203
last-result)))
195204
(list (car bounds) (cdr bounds)
196205
(lambda (prefix pred action)
@@ -205,8 +214,7 @@ performed by `cider-annotate-completion-function'."
205214
(cond ((eq action 'metadata) `(metadata (category . cider))) ;; defines a completion category named 'cider, used later in our `completion-category-overrides` logic.
206215
((eq (car-safe action) 'boundaries) nil)
207216
(t (with-current-buffer (current-buffer)
208-
(complete-with-action action
209-
(funcall complete prefix) prefix pred)))))
217+
(complete-with-action action (funcall complete) prefix pred)))))
210218
:annotation-function #'cider-annotate-symbol
211219
:company-kind #'cider-company-symbol-kind
212220
:company-doc-buffer #'cider-create-compact-doc-buffer
@@ -264,12 +272,6 @@ in the buffer."
264272
cider-company-unfiltered-candidates
265273
"CIDER backend-driven completion style."))
266274

267-
;; Currently CIDER completions only work for `basic`, and not `initials`, `partial-completion`, `orderless`, etc.
268-
;; So we ensure that those other styles aren't used with CIDER, otherwise one would see bad or no completions at all.
269-
;; This `add-to-list` call can be removed once we implement the other completion styles.
270-
;; (When doing that, please refactor `cider-enable-flex-completion' as well)
271-
(add-to-list 'completion-category-overrides '(cider (styles basic)))
272-
273275
(defun cider-company-enable-fuzzy-completion ()
274276
"Enable backend-driven fuzzy completion in the current buffer.
275277
@@ -292,6 +294,8 @@ Only affects the `cider' completion category.`"
292294
(setq completion-category-overrides (seq-remove (lambda (x)
293295
(equal 'cider (car x)))
294296
completion-category-overrides))
297+
(unless found-styles
298+
(setq found-styles '(styles basic)))
295299
(unless (member 'flex found-styles)
296300
(setq found-styles (append found-styles '(flex))))
297301
(add-to-list 'completion-category-overrides (apply #'list 'cider found-styles (when found-cycle

doc/modules/ROOT/pages/usage/code_completion.adoc

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,27 @@ is already properly indented.
3737

3838
== Completion styles
3939

40-
CIDER defines (via the `completion-styles-alist` Elisp variable) a completion category named `cider`.
40+
CIDER defines a specialized completion category through the `cider-complete-at-point` function,
41+
added to `completion-at-point-functions`, establishing a dedicated completion category named
42+
`cider`.
4143

42-
The `cider` completion category currently only supports `basic` completion styles (and not `partial-completion`, `orderless`, etc),
43-
and `flex`, optionally (read more below).
44+
The CIDER completion at point function supports most completion styles, including
45+
`partial-completion`, `orderless` and `flex` (read more below).
4446

45-
CIDER declares so in this fashion:
47+
48+
Sometimes the user may want to use a different completion style just for the CIDER
49+
complete at point function. That can be achieved by setting
50+
`completion-category-overrides`, overwriting the completion style of the CIDER
51+
complete at point function. The following snippet accomplishes that:
4652

4753
[source,lisp]
4854
----
4955
(add-to-list 'completion-category-overrides '(cider (styles basic)))
5056
----
5157

58+
This specifies that the `cider` completion category should employ the basic completion style by
59+
default.
60+
5261
You can also enable the `flex` completion style by activating xref:usage/code_completion.adoc#fuzzy-candidate-matching[fuzzy candidate matching].
5362

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

132141
=== Fuzzy candidate matching
133142

134-
By default, CIDER will provide completion candidates with the
135-
assumption that whatever you've typed so far is a prefix of what
136-
you're really trying to type. For example, if you type `map-` then
137-
you'll only get completion candidates that have `map-` as the
138-
beginning of their names. Sometimes, you don't know the exact prefix
139-
for the item you want to type. In this case, you can get
140-
CIDER-specific "fuzzy completion" by setting up in your Emacs init file:
143+
By default, CIDER will use the completion styles defined in
144+
`completion-styles`, the defaults being `(basic partial-completion
145+
emacs22)` since Emacs 23. For a better description of how those
146+
completion styles operates, refer to the official Emacs manual on
147+
https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion-Styles.html[how completion alternatives are chosen].
148+
149+
CIDER provides a function to enable the `flex` completion style for CIDER-specific
150+
completions. If you wish to enable that, you can add this to your config:
141151

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

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

149-
Now, `company-mode` will accept certain fuzziness when matching
150-
candidates against the prefix. For example, typing `mi` will show you
151-
`map-indexed` as one of the possible completion candidates and `cji`
152-
will complete to `clojure.java.io`. Different completion examples are
153-
shown
159+
Now, `company-mode` (and other completion packages like `corfu`) will
160+
accept certain fuzziness when matching candidates against the
161+
prefix. For example, typing `mi` will show you `map-indexed` as one of
162+
the possible completion candidates and `cji` will complete to
163+
`clojure.java.io`. Different completion examples are shown
154164
https://github.com/alexander-yakushev/compliment/wiki/Examples[here].
155165

156166
NOTE: `cider-company-enable-fuzzy-completion` (now deprecated) should be used for Emacs < 27.
@@ -189,18 +199,6 @@ keys to cancel the prompt by customizing:
189199
(funcall f a b))))
190200
----
191201

192-
=== Changing the completion style
193-
194-
Sometimes the user may want to use a different completion style just for the CIDER
195-
complete at point function. That can be achieved by setting
196-
`completion-category-defaults`, overriting the completion style of the CIDER
197-
complete at point function. The following snippet accomplishes that:
198-
199-
[source,lisp]
200-
----
201-
(add-to-list 'completion-category-defaults '(cider (styles basic)))
202-
----
203-
204202
=== Updating stale classes and methods cache
205203

206204
Sometimes, the completion fails to recognize new classes that came with

test/cider-completion-tests.el

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,29 @@
3636
(let ((old-value completion-category-overrides))
3737
(unwind-protect
3838
(progn
39-
(it "adds `flex'"
40-
(cider-enable-flex-completion)
41-
(expect (member 'flex (assq 'styles (assq 'cider completion-category-overrides)))
42-
:to-be-truthy))
39+
(it "adds `flex' and `basic' as a fallback"
40+
(let ((expected-category-overrides '((cider (styles basic flex)))))
41+
(cider-enable-flex-completion)
42+
(expect (member 'flex (assq 'styles (assq 'cider completion-category-overrides)))
43+
:to-be-truthy)
44+
(expect (member 'basic (assq 'styles (assq 'cider completion-category-overrides)))
45+
:to-be-truthy)
46+
(expect completion-category-overrides :to-equal expected-category-overrides)))
4347

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

52+
(it "adds just `flex' if there is another style present"
53+
(setq completion-category-overrides '((cider (styles partial-completion))))
54+
(cider-enable-flex-completion)
55+
(expect (member 'flex (assq 'styles (assq 'cider completion-category-overrides)))
56+
:to-be-truthy)
57+
(expect (member 'partial-completion (assq 'styles (assq 'cider completion-category-overrides)))
58+
:to-be-truthy)
59+
(expect (member 'basic (assq 'styles (assq 'cider completion-category-overrides)))
60+
:to-be nil))
61+
4862
(it "doesn't re-add `flex' if already present, preserving `cycle' as well"
4963
(let ((with-flex-and-cycle '((cider (styles basic flex)
5064
(cycle t)))))

0 commit comments

Comments
 (0)