Closed vadim-zyamalov closed 2 years ago
Hello! Thanks for fantastic Vertico and Corfu!
Thanks! You are welcome!
I'm terribly stuck attempting to merge outputs of several capf's. For example, I want to have the ability to use corfu when I try to enter a file name in the code (for example in Python open function). As I understand cape-super-capf is the thing I need.
No, cape-super-capf
is probably not the tool you want to use since it can only merge certain kinds of capfs. You cannot merge cape-file
and lsp since the file capf is too dynamic. cape-super-capf
can merge capfs like dabbrev+keyword+dict etc.
For your use cases it probably suffices to add cape-file
and cape-dabbrev
to the completion-at-point-functions
list as described in the README. Then it should be possible to complete inside comments and string literals. For all other cases the lsp client will take over.
I suggest you don't use cape-super-capf
and the other transformers for now. They are not easy to use and only useful in special scenarios. I recommend the configuration given in the README. I hope this helps!
Maybe there has been a misunderstanding with regards to cape-super-capf
? The purpose of the super capf is to merge multiple capfs into one. Company has a similar feature where you can group multiple backends such that the candidates appear together. This feature is quite limited and does not work with all backends, in both Cape and Company.
However it is not needed at all to use super capf to make multiple backends available for completion. The only issue is that then the completion backends are tried one by one until one of them succeeds. In the case of lsp, lsp will succeed most often. But in string literals etc the cape-file backend can take over.
I added some clarifications to https://github.com/minad/cape#super-capf---merging-multiple-capfs. Please let me know what you think.
However it is not needed at all to use super capf to make multiple backends available for completion. The only issue is that then the completion backends are tried one by one until one of them succeeds. In the case of lsp, lsp will succeed most often. But in string literals etc the cape-file backend can take over.
I've already tried the recipe from README. But it seems that LSP is too greedy and cape can't take over it. Well, I'll use a separate keybinding. Not so convenient as TAB but still.
I added some clarifications to https://github.com/minad/cape#super-capf---merging-multiple-capfs. Please let me know what you think.
It's more clear now, thanks!
Sorry for wasting your time!
No worrries, this was an absolutely legitimate question. Btw, this is how you can turn a greedy (exclusive) capf greedy-capf
into a non-exclusive non-greedy-capf
:
(fset 'non-greedy-capf (cape-capf-with-properties #'greedy-capf :exclusive 'no))
You can then register the non-greedy-capf
instead of the greedy-capf
in the completion-at-point-functions
list. Maybe this helps with the lsp mode capf.
Hooray, your reply pushed me towards a solution! I did the following:
completion-at-point-functions
lsp-completion-mode
Now cape-capfs are called just before lsp-completion-at-point
! Look at :init
and :hook
sections.
(use-package lsp-mode
;; :ensure t
:straight t
:commands (lsp lsp-deferred)
:init
(defun my/update-completions-list ()
(progn
(push #'cape-dabbrev completion-at-point-functions)
(push #'cape-file completion-at-point-functions)))
:config
(setq lsp-enable-file-watchers nil)
(setq lsp-keymap-prefix "C-c l")
(lsp-enable-which-key-integration t)
(define-key lsp-mode-map (kbd "C-c l") lsp-command-map)
:custom
(lsp-completion-provider :none)
:hook
(lsp-completion-mode . my/update-completions-list))
That's also a viable approach, however I am not sure if you prefer if cape-file/cape-dabbrev takes precedence over the lsp capf.
Your suggested solution works like a charm as well!
Modified version of use-package
init section for lsp-mode
:
:init
(defun my/update-completions-list ()
(progn
(fset 'non-greedy-lsp (cape-capf-with-properties #'lsp-completion-at-point :exclusive 'no))
(setq completion-at-point-functions
'(non-greedy-lsp cape-file cape-dabbrev))))
Thanks again for your help!
I've been trying some of the suggestions above but, with cape version 2022-04-28, there does not appear to be a function cape-capf-with-properties defined anywhere. What am I missing please? Thank you.
It is called cape-capf-properties
now.
(cape-capf-properties #'lsp-completion-at-point :exclusive 'no)
Thank you. I had tried that (having searched the .el file) but it doesn't seem to work for me. I have the following:
(fset 'non-greedy-dict (cape-capf-properties #'cape-dict :exclusive 'no))
(fset 'non-greedy-dabbrev (cape-capf-properties #'cape-dabbrev :exclusive 'no))`
(setq-local completion-at-point-functions (list #'non-greedy-dict #'non-greedy-dabbrev #'cape-ispell))
and the behaviour is the same as the greedy version. For instance, if I swap the first two entries around, the matches found change (and are always from the first source).
@ericsfraga Not sure what you are trying to achieve here, but cape-dabbrev
and cape-dict
are already marked as :exclusive no
. So cape-capf-properties
is a no-op here.
Okay, that's useful to know. What I wish to achieve is to have the completion list be a union of the lists each of the cap functions would return, not just giving me the list from the first function that has matches. Is this possible?
Yes, this is what cape-super-capf
is for. You can combine cape-dabbrev
, cape-dict
and cape-keyword
for example. But note that cape-super-capf
is fragile and its capabilites are limited. See https://github.com/minad/cape/#super-capf---merging-multiple-capfs for details and also for the warning.
Personally I don't use cape-super-capf
. I am more happy to explicitly trigger completion functions, e.g., by binding them to C-c p d
for dabbrev, C-c p f
for file paths etc. You can use even shorter trigger keys in your personal configuration, e.g., M-+ d
, M-+ f
, ...
Yes, I had seen cape-super-capf
and that's what I tried first. For some reason, this:
(setq-local completion-at-point-functions
(list (cape-super-capf #'cape-dabbrev #'cape-dict #'cape-ispell)))
does not work. When I ask for completion-at-point
, I get nothing at all. Apologies if I'm missing something completely obvious here.
Note I have tried without -local
as well.
And, yes, I note that I could have the different completion sources on different bindings. I will fall back to this if need be but would prefer to have TAB work across multiple sources if at all possible.
For me it works when I evaluate the following in a scratch buffer:
(setq-local completion-at-point-functions
(list (cape-super-capf #'cape-dabbrev #'cape-dict)))
Strange. It doesn't for me (just tried exactly this in scratch. I must have something else messing this up. Thank you for the help. If I figure it out, I will update here. Interestingly, corfu works, showing entries from more than one source.
Yes, it indeed doesn't work for default completion. I don't know why. (EDIT: I pushed a fix.)
Hello! Thanks for fantastic Vertico and Corfu! I'm terribly stuck attempting to merge outputs of several capf's. For example, I want to have the ability to use corfu when I try to enter a file name in the code (for example in Python open function). As I understand
cape-super-capf
is the thing I need. But I can't understand how to configure it properly. When I invoke corfu it show me only completion variants from lsp-mode. I have to invokecape-file
withM-x cape-file
explicitly to show corfu sub-frame with filename completion variants.I'm using lsp-mode in Emacs 27.2. I try to configure cape as follows
Sorry if it's a stupid question but I'm not so good at emacs configuration yet...