minad / cape

🦸cape.el - Completion At Point Extensions
GNU General Public License v3.0
608 stars 22 forks source link

elisp-completion-at-point and cape-file #53

Closed duelaugh closed 2 years ago

duelaugh commented 2 years ago

In the README, you provide the following code for registering cape-* functions in the global completion-at-point-functions abnormal hook: (add-to-list 'completion-at-point-functions #'cape-file)

I was experimenting with the various capfs, when I encountered a behavior I cannot explain.

In the *scratch* buffer, the value of completion-at-point-functions is (elisp-completion-at-point t). The default (global) value of completion-at-point-functions is (cape-file tags-completion-at-point-function).

Now, the t value in the end of the buffer local hook list ensures that the hooks registered in the global hook list are tried after the elisp capf.

In the *scratch* buffer, when I tried to complete (complete-at-point) ~/ path, there was only a match when it was inside a string literal, which was unexpected - so I started experimenting.

I noticed that if cape-file was called before elisp-completion-at-point (by prepending cape-file to the buffer local hook, or by moving t before elisp-completion-at-point), it worked as expected (completing ~/ path inside and outside of string literals). It also worked when I removed elisp-completion-at-point altogether.

Why does one capfs affect others? Is there something I miss?

minad commented 2 years ago

Capfs are tried in order. When the (exclusive) elisp-completion-at-point function takes over, even if it doesn't return completion candidates, cape-file doesn't get a chance to run. The elisp Capf doesn't take over (returns nil) inside string literals. It is possible to mark a Capf as non-exclusive, the Cape Capfs are non-exclusive by default. Try these three settings:

(setq-local completion-at-point-functions
            '(cape-file elisp-completion-at-point))

(setq-local completion-at-point-functions
            '(elisp-completion-at-point cape-file))

(setq-local completion-at-point-functions
            (list
             (cape-capf-properties #'elisp-completion-at-point :exclusive 'no)
             #'cape-file))