reddit / emacs

Sample usage of Cape — Completion At Point Extensions

FluentFelicity · 2022-03-13 06:16
Hi all. I previously posted about [Vertico, Marginalia, and Orderless](https://www.reddit.com/r/emacs/comments/syk4k3/sample_vertico_marginalia_and_orderless/) and [Corfu, Kind-icon, and Corfu-doc](https://www.reddit.com/r/emacs/comments/t38kkh/sample_corfu_kindicon_and_corfudoc_configuration/). This time I wrote on [Cape](https://kristofferbalintona.me/posts/cape/)! I highly recommend using `cape` to those who use `corfu`. It provides many useful `completion-at-point-functions` as well as transformers such as `cape-capf-buster` and `cape-capf-silent`. My favorite is `cape-company-to-capf` which converts `company` backends to `completion-at-point-functions`! This was the killer feature for me. Though this post is less thorough and has less "developed" code than my previous two posts, I hope a few of you still find it useful :) Edit: Some of you may notice the website redesign. I hope it adds clarity.
doolio_ · 2022-03-13 12:23
Is there an unwanted space in your use-package form for the first cape-tex. Also, why define three bindings for it?
hkjels · 2022-03-13 12:47
For the un-enlightened, what’s the point of Corfu and Cape, if you still rely on company-backend’s? Or, why not just use company?
emax-gomax · 2022-03-13 14:27
I'm unenlightened as well but let me give this a try. Corfu is a Completion-at-point-functions (CAPF) frontend, kinda like the little box of completions that company shows as you type. The difference is that Corfu uses the builtin completion mechanism that ships with standard emacs. Company has its own definitions for this sort of thing. Cape provides a bunch of completion functions you can use with corfu, but you don't have to. Their compatible with CAPF so any frontend that uses CAPF (such as corfu) can be used with it. And being able to run company backends with cape lets you use corfu with company completions (which is important since company is basically the standard completion framework used by most non-builtin emacs packages including lsp-mode and eglot). Essentially you can semlessly use the existing infrastructure for completions offered by company with whatever frontend (in this case corfu) you'd like. Why is that a good thing? Because it makes Emacs more plug and play. We've gotten so many recent improvements to minibuffer completions in Emacs because we've decoupled the same high level features that packages like ivy and helm provide into more independent features that we can configure independently. You don't like the way ivy treats your patterns as Regex, write a new completion-style like orderless but keep using everything else like you have been. You don't like how helm looks? Pick up a new frontend like vertico or selectrum but keep using all the same commands and tools you have because their all generic. It's this sort of ethos that I really like about the recent trends in Emacs, nothing really has to do everything anymore so everything only needs to be specialised for what it's interested in.
JDRiverRun · 2022-03-13 15:14
>since company is basically the standard completion framework used by most non-builtin emacs packages including lsp-mode and eglot) Company is indeed the default UI used by lsp-mode and eglot (and others), but the [actual completion functionality](https://github.com/emacs-lsp/lsp-mode/blob/ddb776037fc073473e0da9d07e63f57242b212fb/lsp-completion.el#L416) itself is provided by... *a standard Emacs CAPF*! This isn't actually too surprising. Company has for a long time [recommended](https://github.com/company-mode/company-mode/blob/master/CONTRIBUTING.md#guidelines-for-third-party-packages) this route for new backends: a standard CAPF, with some special extra properties (like `:company-kind`), which have become *de facto* standards. It is, for the reasons you mentioned, a **very good thing** to separate backend completion supplier capabilities from front-end sorting/selecting/UI. For this reason, it is in fact easy to switch the front-end of e.g. lsp-mode [from company to corfu](https://github.com/minad/corfu/wiki#configuring-corfu-for-lsp-mode). I see the ability of CAPE to "translate" results from company backends as a transitionary convenience. Most new modes are using CAPFs from the start. But one significant advantage that company had over traditional CAPF's is that you could *merge* results from multiple backends into one list of completions (think: lsp results and dabbrev together); CAPE brings that same functionality (and much more) to Emacs' standard completion framework, making CAPF's effectively infinitely tailorable. You can even "edit" the completions themselves, using `cape-capf-with-predicate`. Here's an example from my config: (defun my/ignore-elisp-keywords (cand) (or (not (keywordp cand)) (eq (char-after (car completion-in-region--data)) ?:))) (defun my/setup-elisp () (setq-local completion-at-point-functions `(,(cape-super-capf (cape-capf-with-predicate #'elisp-completion-at-point #'my/ignore-elisp-keywords) #'cape-dabbrev) cape-file) cape-dabbrev-min-length 5)) This setup function trivially creates a custom merged capf including: 1. Normal elisp completions, but omitting keywords unless the candidate explicitly starts with a colon. 2. dabbrev results 3. If these two fail, `cape-file` is tried. into one "super" capf. The options for combining/editing/etc. are obviously endless. Bottom line: if there's something you don't like about your completion results... just fix it with CAPE.
FluentFelicity · 2022-03-13 15:38
Yes, you're right! Just fixed it. Nice catch on that space. Also, there is really no reason to have three bindings for it. I took the binding scheme straight from `cape`'s readme.
FluentFelicity · 2022-03-13 15:44
Fantastic response! I've added a link to your comment to my post
JDRiverRun · 2022-03-13 16:22
One thing that confused me early on with CAPFs that's worth mentioning: You've *always* been able to add multiple CAPFs to the variable `completion-at-point-functions`, as is done in your example. This isn't CAPE-specific (other than the fact that CAPE provides a few simple CAPFs for easy use). But this "multi-CAPF" setup may not function like you expect. The reason is that CAPF completion is a two-step process. **Step 1**: Each CAPF on the list is asked first *whether it can complete at this location*. So if you are in a string, a CAPF might say "no I can't complete in strings", and just return nil. The first CAPF on the list to say it can *in principle* provide some completions "wins". But it hasn't yet actually checked for completions! **Step 2:** The winning CAPF is asked for the completions at point. But maybe it returns no completions at all! If so, completion is over. This is fine if say the first CAPF on your list works outside of strings, and the next works inside of strings; they'll dovetail nicely. But what if they both work "in the same place"? CAPFs can themselves set a property `:exclusive 'no`, which means "if Step 2 fails, go back to Step 1" and try the next CAPF, but in practice none do, since Emacs has some bugs related to this. To me it's strange to let the CAPFs themselves decide this; this should be a user choice. Cape makes that possible.
JDRiverRun · 2022-03-13 16:24
>what’s the point of Corfu and Cape, if you still rely on company-backend’s? Only as a temporary workaround for older completion backends that still are company-specific (which are fewer and fewer). Note that most completions even in company get provided by normal emacs-standard CAPF's, including those from lsp-mode and eglot.
JDRiverRun · 2022-03-13 16:28
>Company has its own definitions for this sort of thing. But it also has `company-capf` to bridge to the Emacs CAPF universe. In practice most modern modes are using the CAPF approach (with some custom company-originated properties like `:company-doc-buffer`), so as to separate UI from backend.
oantolin · 2022-03-13 17:36
There is a reason for the multiple bindings! Each is specialized to complete things that start with the last character in the binding, so the caret binding is to complete superscripts, the underscore to complete subscripts and the backslash for the bulk of the TeX input method names of glyphs. If you use `C-c p \`, then cape-tex will supply the initial backslash for you an you just have to type the subsequent letters.
doolio_ · 2022-03-13 18:04
Yes, of course. It has been too long since I wrote any LaTex. Thank you.
pajuch · 2022-03-13 18:29
Was waiting for this :)
ram535 · 2022-03-13 19:37
Is it possible to use `corfu` and `cape` with `vterm`?
FluentFelicity · 2022-03-13 19:39
I don't think it is. Eshell definitely though
7890yuiop · 2022-03-14 05:35
What would that mean?
ram535 · 2022-03-14 22:11
Getting autocompletion for file, directories, history and commands names.
7890yuiop · 2022-03-14 23:32
How would that work? vterm doesn't know any of that stuff (it's just a terminal for whatever arbitrary process is running).
ram535 · 2022-03-15 01:30
I don't know that's why I was asking if it is possible.
7890yuiop · 2022-03-15 03:10
You'd need a chain of interactions between corfu/cape, vterm, and the inferior process to ask that process (which might be anything at all) for completions; for the process to understand the request and return them in a way that vterm could then consume *without* changing the state of the terminal; pass them back to the completion UI in Emacs; process a selection; pass that *back* through vterm and send the completion to the inferior process... These sorts of thing are *possible*, and your shell might well facilitate it (e.g. for `bash` see the `compgen` builtin), but you need *all* of the components to take part in the process, and a terminal sitting in the middle is a huge complication. (Conversely this is fairly common for comint-based interfaces which know exactly which process they are talking to, and which communicate directly with that process.) In practice it's probably safe to assume it's not happening.
T_Verron · 2022-03-15 08:19
>(Conversely this is fairly common for comint-based interfaces which know exactly which process they are talking to, and which communicate directly with that process.) For completeness, `shell` is the comint-based terminal emulator/shell/whatever (if someone cares about the difference, please just tell me which is correct and I'll edit :) ). I don't know if it asks the underlying process for completion candidates. Anyway I wouldn't recommend using it as a replacement for the terminal. `comint` just sends text out and gets text in, with no room for interactions. So anything more complicated than this simple I/O model (even `less`) will not work properly. But if you just need to run a couple of commands, it's nicer than `term` or `vterm` because you retain all of emacs' bindings.
MistakeNotDotDotDot · 2022-03-16 04:20
Yeah, I hadn't looked at minibuffer completion since I just installed selectrum a few years ago and seeing stuff like corfu and orderless exist blew my mind.
OutsideNo1877 · 2022-09-26 11:20
I like cape except for the fact that for whatever reason ya snippets dont seem to work with the company backend for which kinda kills the usability
jvillasante · 2022-11-05 21:30
Is there a way to configure eglot + corfu + cape in a way that when auto-completing the auto-completion list shows not just the function name but also the parameters? Right now eglot only shows function names on completion list (and expands) even without parens, which is super weird. company does this by default, but I haven't been able to make it work with corfu.
JDRiverRun · 2022-12-17 14:55
Should echo in the minibuffer. Also, look into the new corfu-popupinfo. Really nice.