feat(corfu): more CAPFs and ergonomy changes

Add various CAPFs from cape:
- `cape-dabbrev`;
- `cape-emoji`;
- `cape-dict`;
Fixed some CAPFs via cape:
- Make non-exclusive, purified and silent `pcomplete-completions-at-point`;
- Make non-exclusive and non-interruptable `lsp-completion-at-point`;
- Make non-exclusive `eglot-completion-at-point`;
- Make non-exclusive `comint-completion-at-point`;
Fix and improve keybindings:
- Smart `DEL`/`backspace` for `+tng`;
- Smart `RET`;
Add depth to CAPFs, allowing ordering to be adjustable.
Enable in minibuffer.
This commit is contained in:
StrawberryTea 2023-10-30 14:36:19 -04:00 committed by Luigi Sartor Piucco
parent aa900c8158
commit 62b2cf9cbf
No known key found for this signature in database
GPG key ID: 6FF1A01853A47A66
2 changed files with 113 additions and 24 deletions

View file

@ -26,6 +26,14 @@ and highly non-native, but has some extra features and more maturity.
- +orderless :: - +orderless ::
Pull in [[doom-package:orderless]] if necessary and apply multi-component Pull in [[doom-package:orderless]] if necessary and apply multi-component
completion (still needed if [[doom-module::completion vertico]] is active). completion (still needed if [[doom-module::completion vertico]] is active).
- +dabbrev ::
Enable and configure [[doom-package:dabbrev]] as a close-to-universal CAPF
fallback.
- +dict ::
Enable and configure dictionary completion for text modes and related regions
in programming modes.
- +emoji ::
Enable and configure emoji completion via the emoji input method.
** Packages ** Packages
- [[doom-package:corfu]] - [[doom-package:corfu]]
@ -63,26 +71,25 @@ By default, completion gets triggered after typing 2 non-space consecutive
characters, or by means of the [[kbd:][C-SPC]] keybinding at any moment. While the popup characters, or by means of the [[kbd:][C-SPC]] keybinding at any moment. While the popup
is visible, the following relevant keys are available: is visible, the following relevant keys are available:
| Keybind | Description | | Keybind | Description |
|----------+------------------------------------------------------------------| |----------+---------------------------------------------------------|
| [[kbd:][<down>]] | Go to next candidate | | [[kbd:][<down>]] | Go to next candidate |
| [[kbd:][<up>]] | Go to previous candidate | | [[kbd:][<up>]] | Go to previous candidate |
| [[kbd:][C-n]] | Go to next candidate | | [[kbd:][C-n]] | Go to next candidate |
| [[kbd:][C-p]] | Go to previous candidate | | [[kbd:][C-p]] | Go to previous candidate |
| [[kbd:][C-j]] | (evil) Go to next candidate | | [[kbd:][C-j]] | (evil) Go to next candidate |
| [[kbd:][C-k]] | (evil) Go to previous candidate | | [[kbd:][C-k]] | (evil) Go to previous candidate |
| [[kbd:][C-<down>]] | Go to next doc line | | [[kbd:][C-<down>]] | Go to next doc line |
| [[kbd:][C-<up>]] | Go to previous doc line | | [[kbd:][C-<up>]] | Go to previous doc line |
| [[kbd:][C-S-n]] | Go to next doc line | | [[kbd:][C-S-n]] | Go to next doc line |
| [[kbd:][C-S-p]] | Go to previous doc line | | [[kbd:][C-S-p]] | Go to previous doc line |
| [[kbd:][C-S-j]] | (evil) Go to next doc line | | [[kbd:][C-S-j]] | (evil) Go to next doc line |
| [[kbd:][C-S-k]] | (evil) Go to previous doc line | | [[kbd:][C-S-k]] | (evil) Go to previous doc line |
| [[kbd:][C-h]] | Toggle documentation (if available) | | [[kbd:][C-h]] | Toggle documentation (if available) |
| [[kbd:][M-m]] | Export to minibuffer (if [[doom-module::completion vertico]]) | | [[kbd:][M-m]] | Export to minibuffer (if [[doom-module::completion vertico]]) |
| [[kbd:][M-S-j]] | (evil) Export to minibuffer (if [[doom-module::completion vertico]]) | | [[kbd:][M-j]] | (evil) Export to minibuffer (if [[doom-module::completion vertico]]) |
| [[kbd:][RET]] | Insert candidate | | [[kbd:][RET]] | Insert candidate |
| [[kbd:][SPC]] | (after wildcard) Reset completion | | [[kbd:][SPC]] | Quit autocompletion after a wildcard or pass-through |
| [[kbd:][DEL]] | Reset completion |
| [[kbd:][C-SPC]] | Complete (unless [[doom-module::completion corfu +tng]]) | | [[kbd:][C-SPC]] | Complete (unless [[doom-module::completion corfu +tng]]) |
| [[kbd:][C-SPC]] | (when completing) Insert separator DWIM (see below) | | [[kbd:][C-SPC]] | (when completing) Insert separator DWIM (see below) |
@ -95,6 +102,7 @@ following additional binds:
| [[kbd:][TAB]] | Complete | | [[kbd:][TAB]] | Complete |
| [[kbd:][TAB]] | (when completing) Go to next candidate | | [[kbd:][TAB]] | (when completing) Go to next candidate |
| [[kbd:][S-TAB]] | (when completing) Go to previous candidate | | [[kbd:][S-TAB]] | (when completing) Go to previous candidate |
| [[kbd:][DEL]] | (when completing) Reset completion DWIM-style |
** Searching with multiple keywords ** Searching with multiple keywords
If the [[doom-module::completion corfu +orderless]] flag is enabled, users can If the [[doom-module::completion corfu +orderless]] flag is enabled, users can
@ -129,15 +137,18 @@ A few variables may be set to change behavior of this module:
Configures behavior for exact matches. Its default is nil, and it's Configures behavior for exact matches. Its default is nil, and it's
recommended to leave it at that. Otherwise, single matches on snippet keys recommended to leave it at that. Otherwise, single matches on snippet keys
expand immediately. expand immediately.
- [[var:+corfu-buffer-scanning-size-limit]] ::
Sets the maximum buffer size to be scanned by ~cape-dabbrev~. Defaults to 1
MB. Set this if you are having performance problems using the CAPF.
** Adding CAPFs to a mode ** Adding CAPFs to a mode
To add other CAPFs on a mode-per-mode basis, put either of the following in your To add other CAPFs on a mode-per-mode basis, put either of the following in your
~config.el~: ~config.el~:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(add-hook! some-mode (add-to-list 'completion-at-point-functions #'some-capf)) (add-hook! some-mode (add-hook 'completion-at-point-functions #'some-capf depth t))
;; OR, but note the different call signature ;; OR, but note the different call signature
(add-hook 'some-mode-hook (lambda () (add-to-list 'completion-at-point-functions #'some-capf))) (add-hook 'some-mode-hook (lambda () (add-hook 'completion-at-point-functions #'some-capf depth t)))
#+end_src #+end_src
~DEPTH~ above is an integer between -100, 100, and defaults to 0 of omitted. Also ~DEPTH~ above is an integer between -100, 100, and defaults to 0 of omitted. Also
@ -147,6 +158,17 @@ accepts the quoted arguments form above.
* Troubleshooting * Troubleshooting
[[doom-report:][Report an issue?]] [[doom-report:][Report an issue?]]
If you have performance issues with ~cape-dabbrev~, the first thing I recommend
doing is to look at the list of buffers Dabbrev is scanning:
#+begin_src emacs-lisp
(dabbrev--select-buffers) ; => (#<buffer README.org> #<buffer config.el<3>> #<buffer cape.el> ...)
(length (dabbrev--select-buffers)) ; => 37
#+end_src
... and modify ~dabbrev-ignored-buffer-regexps~ or ~dabbrev-ignored-buffer-modes~
accordingly.
* Frequently asked questions * Frequently asked questions
/This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]] /This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]]

View file

@ -1,5 +1,8 @@
;;; completion/corfu/config.el -*- lexical-binding: t; -*- ;;; completion/corfu/config.el -*- lexical-binding: t; -*-
(defvar +corfu-buffer-scanning-size-limit (* 1 1024 1024) ; 1 MB
"Size limit for a buffer to be scanned by `cape-dabbrev'.")
;; ;;
;;; Packages ;;; Packages
(use-package! corfu (use-package! corfu
@ -18,7 +21,7 @@
t) t)
corfu-cycle t corfu-cycle t
corfu-separator (when (modulep! +orderless) ?\s) corfu-separator (when (modulep! +orderless) ?\s)
corfu-preselect 'valid corfu-preselect (if (modulep! +tng) 'prompt 'valid)
corfu-count 16 corfu-count 16
corfu-max-width 120 corfu-max-width 120
corfu-preview-current 'insert corfu-preview-current 'insert
@ -41,6 +44,13 @@
:map corfu-mode-map :map corfu-mode-map
"C-M-i" #'completion-at-point) "C-M-i" #'completion-at-point)
(add-hook! 'minibuffer-setup-hook
(defun +corfu-enable-in-minibuffer ()
"Enable Corfu in the minibuffer if `completion-at-point' is bound."
(when (where-is-internal #'completion-at-point (list (current-local-map)))
(setq-local corfu-echo-delay nil)
(corfu-mode +1))))
(after! evil (after! evil
(add-hook 'evil-insert-state-exit-hook #'corfu-quit)) (add-hook 'evil-insert-state-exit-hook #'corfu-quit))
@ -78,10 +88,67 @@
:init :init
(add-hook! prog-mode (add-hook! prog-mode
(defun +corfu-add-cape-file-h () (defun +corfu-add-cape-file-h ()
(add-to-list 'completion-at-point-functions #'cape-file))) (add-hook 'completion-at-point-functions #'cape-file -10 t)))
(add-hook! (org-mode markdown-mode) (add-hook! (org-mode markdown-mode)
(defun +corfu-add-cape-elisp-block-h () (defun +corfu-add-cape-elisp-block-h ()
(add-to-list 'completion-at-point-functions #'cape-elisp-block))) (add-hook 'completion-at-point-functions #'cape-elisp-block 0 t)))
;; Enable Dabbrev completion basically everywhere as a fallback.
(when (modulep! +dabbrev)
;; Set up `cape-dabbrev' options.
(defun +dabbrev-friend-buffer-p (other-buffer)
(< (buffer-size other-buffer) +corfu-buffer-scanning-size-limit))
(after! dabbrev
(setq cape-dabbrev-check-other-buffers t
dabbrev-friend-buffer-function #'+dabbrev-friend-buffer-p
dabbrev-ignored-buffer-regexps
'("^ "
"\\(TAGS\\|tags\\|ETAGS\\|etags\\|GTAGS\\|GRTAGS\\|GPATH\\)\\(<[0-9]+>\\)?")
dabbrev-upcase-means-case-search t)
(add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode)
(add-hook! (prog-mode text-mode conf-mode comint-mode minibuffer-setup
eshell-mode)
(defun +corfu-add-cape-dabbrev-h ()
(add-hook 'completion-at-point-functions #'cape-dabbrev 20 t)))))
;; Complete emojis :).
(when (and (modulep! +emoji) (> emacs-major-version 28))
(add-hook! (prog-mode conf-mode)
(defun +corfu-add-cape-emoji-h ()
(add-hook 'completion-at-point-functions
(cape-capf-inside-faces
(cape-capf-prefix-length #'cape-emoji 1)
;; Only call inside comments and docstrings.
'tree-sitter-hl-face:doc 'font-lock-doc-face
'font-lock-comment-face 'tree-sitter-hl-face:comment)
10 t)))
(add-hook! text-mode
(defun +corfu-add-cape-emoji-text-h ()
(add-hook 'completion-at-point-functions
(cape-capf-prefix-length #'cape-emoji 1) 10 t))))
;; Enable dictionary-based autocompletion.
(when (modulep! +dict)
(add-hook! (prog-mode conf-mode)
(defun +corfu-add-cape-dict-h ()
(add-hook 'completion-at-point-functions
(cape-capf-inside-faces
;; Only call inside comments and docstrings.
#'cape-dict 'tree-sitter-hl-face:doc 'font-lock-doc-face
'font-lock-comment-face 'tree-sitter-hl-face:comment)
40 t)))
(add-hook! text-mode
(defun +corfu-add-cape-dict-text-h ()
(add-hook 'completion-at-point-functions #'cape-dict 40 t))))
;; Make these capfs composable.
(advice-add #'comint-completion-at-point :around #'cape-wrap-nonexclusive)
(advice-add #'eglot-completion-at-point :around #'cape-wrap-nonexclusive)
(advice-add #'lsp-completion-at-point :around #'cape-wrap-nonexclusive)
(advice-add #'pcomplete-completions-at-point :around #'cape-wrap-nonexclusive)
;; From the `cape' readme. Without this, Eshell autocompletion is broken on
;; Emacs28.
(when (< emacs-major-version 29)
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify))
(advice-add #'lsp-completion-at-point :around #'cape-wrap-noninterruptible)) (advice-add #'lsp-completion-at-point :around #'cape-wrap-noninterruptible))
(use-package! yasnippet-capf (use-package! yasnippet-capf