Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Corfu and Company simultaneously in different modes. #321

Closed
hongyi-zhao opened this issue May 1, 2023 · 6 comments
Closed

Using Corfu and Company simultaneously in different modes. #321

hongyi-zhao opened this issue May 1, 2023 · 6 comments

Comments

@hongyi-zhao
Copy link

Dear Corfu maintainers,

I hope this message finds you well. I am an Emacs user who is interested in using the Corfu completion framework in my setup. Before proceeding, I would like to seek your advice on a particular aspect of integrating Corfu alongside another popular completion framework, Company.

I understand that Corfu and Company are both powerful completion frameworks with distinct design philosophies, and typically, users may prefer to use one or the other. However, in my case, I am considering using both frameworks simultaneously but in different editing modes. Specifically, I plan to use Company for programming modes (such as C, Python, Emacs Lisp, etc.) and Corfu for text editing modes (such as Org, Markdown, plain text, etc.).

To achieve this, I intend to enable Company and Corfu in different mode hooks like this:

;; Company
(use-package company
  :hook
  (prog-mode . company-mode) ; Enable Company in programming modes
)

;; Corfu
(use-package corfu
 :hook
(text-mode . corfu-mode)   ; Enable Corfu in text modes
)

My question is whether such a setup is advisable and if there are any known issues or conflicts I should be aware of when using both Corfu and Company in this manner. Additionally, if you have any suggestions or best practices for this kind of configuration, I would greatly appreciate your input.

Thank you in advance for your time and assistance. I look forward to hearing from you and learning more about how to best utilize Corfu in conjunction with Company.

Best regards,
Zhao

@minad
Copy link
Owner

minad commented May 1, 2023

Yes, using Corfu and Company locally per major modes is possible, since Company and Corfu are both local minor modes. However I don't really see the value in doing that, since this leads to an inconsistent UI experience. I would rather use the one I like better in all modes for a consistent UI. Note that you can also use Company backends with Corfu via cape-company-to-capf. Vice versa you can use all Capf backends with Company via company-capf. Why would you want to use one for programming and the other for text modes? I would try to fix my configuration such that one or the other works equally well or better than the other in all modes.

@minad minad closed this as completed May 1, 2023
@hongyi-zhao
Copy link
Author

Note that you can also use Company backends with Corfu via cape-company-to-capf. Vice versa you can use all Capf backends with Company via company-capf.

Do you mean the following?

By using the cape-company-to-capf and company-capf conversion functions, we can achieve interoperability between Corfu and Company. This allows the user to choose one of the completion frameworks and gain access to the functionalities of both by integrating the backends of the other framework into the chosen one.

In particular:

  • If you choose to use Corfu as your primary completion framework, you can use cape-company-to-capf to convert Company backends to CAPF backends, allowing Corfu to utilize them. This means you can have the functionalities provided by Company within Corfu.

  • If you choose to use Company as your primary completion framework, you can integrate the CAPF backends into Company by adding them to company-backends (using company-capf). This means you can have the functionalities provided by Corfu within Company.

In summary, with this approach, you can choose one of the completion frameworks while ensuring that you can access the functionalities provided by both. This allows you to flexibly customize the completion experience according to your needs and preferences. However, it seems that while this interoperability provides a great deal of flexibility, it may also make the configuration more complex. Depending on the specific needs, the user might need to spend some time adjusting and optimizing the configuration to achieve the best results.

Below, I give a concrete example:

Currently, I'm using company-math with the following configuration:

(use-package company-math
  :hook
  ;; This will enable the company-math backend for LaTeX mode
  (LaTeX-mode . (lambda ()
          (setq-local company-backends
                  (append '((company-math-symbols-latex company-latex-commands))
                      company-backends))))
  )

But if I switched to corfu, what adjustment should I do to the above configuration?

Why would you want to use one for programming and the other for text modes?

Just as an example to express my question.

I would try to fix my configuration such that one or the other works equally well or better than the other in all modes.

What's the concrete configuration?

@minad
Copy link
Owner

minad commented May 1, 2023

I argue that the complexity is quite low if you create Capfs from Company backends. Then you also don't have to bother with the interaction of company-backends and completion-at-point-functions. Example:

;; Turn the Company backend into a standard Capf
(defalias 'math-symbols-latex-capf (cape-company-to-capf #'company-math-symbols-latex))

;; Register the Capf buffer-locally in your desired modes
(add-hook 'completion-at-point-functions #'math-symbols-latex-capf nil 'local)

See https://github.com/minad/cape#company-adapter for more details.

@hongyi-zhao
Copy link
Author

hongyi-zhao commented May 1, 2023

Your following example gives me the insight on using multiple 3rd party backends as Capfs when playing with Corfu:

;; Use Company backends as Capfs.
(setq-local completion-at-point-functions
  (mapcar #'cape-company-to-capf
    (list #'company-files #'company-ispell #'company-dabbrev)))

A further issue is the grouping of multiple backends and the order of candidates returned from them. How does Corfu handle this?

@minad
Copy link
Owner

minad commented May 2, 2023

See https://github.com/minad/cape#company-adapter.

@hongyi-zhao
Copy link
Author

hongyi-zhao commented May 6, 2023

For completion of the LaTeX package names, I tried the following but still in vain.

This is simply adapted from the official cape example:

(use-package cape
  ;; Bind dedicated completion commands
  ;; Alternative prefix keys: C-c p, M-p, M-+, ...
  :bind (("C-c p p" . completion-at-point) ;; capf
         ("C-c p t" . complete-tag)        ;; etags
         ("C-c p d" . cape-dabbrev)        ;; or dabbrev-completion
         ("C-c p h" . cape-history)
         ("C-c p f" . cape-file)
         ("C-c p k" . cape-keyword)
         ("C-c p s" . cape-symbol)
         ("C-c p a" . cape-abbrev)
         ("C-c p l" . cape-line)
         ("C-c p w" . cape-dict)
         ("C-c p \\" . cape-tex)
         ("C-c p _" . cape-tex)
         ("C-c p ^" . cape-tex)
         ("C-c p &" . cape-sgml)
         ("C-c p r" . cape-rfc1345))
  :init
  ;; Add `completion-at-point-functions', used by `completion-at-point'.
  ;; NOTE: The order matters!
  (add-to-list 'completion-at-point-functions #'cape-dabbrev)
  (add-to-list 'completion-at-point-functions #'cape-file)
  ;; (add-to-list 'completion-at-point-functions #'cape-elisp-block)
  ;;(add-to-list 'completion-at-point-functions #'cape-history)
  (add-to-list 'completion-at-point-functions #'cape-keyword)
  ;; (add-to-list 'completion-at-point-functions #'cape-tex)
  ;;(add-to-list 'completion-at-point-functions #'cape-sgml)
  ;;(add-to-list 'completion-at-point-functions #'cape-rfc1345)
  (add-to-list 'completion-at-point-functions #'cape-abbrev)
  (add-to-list 'completion-at-point-functions #'cape-dict)
  ;;(add-to-list 'completion-at-point-functions #'cape-symbol)
  ;; (add-to-list 'completion-at-point-functions #'cape-line)

  ;; Use Company backends as Capfs.
  (setq-local completion-at-point-functions
          (mapcar #'cape-company-to-capf
              (list #'company-files #'company-ispell #'company-dabbrev)))
  )

At this point, the completion result is clearly incorrect, as shown in the attached screenshot. Any prompts for further fine-tuning would be greatly appreciated.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants