From 5e542af186932e64b5af2d16aeb1f59390d997f5 Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Sat, 24 Sep 2022 17:33:32 -0300 Subject: [PATCH 01/17] module: add :completion corfu This commit's primary goal is allowing use of [minad/corfu](https://github.com/minad/corfu) as an alternative to [company](https://github.com/company-mode/company-mode). It introduces a module under :completion for this purpose, plus some conditionals on other relevant modules to toggle functionality like lsp back-ends and [minad/cape](https://github.com/minad/cape) capfs for certain modes. Other optional or miscellaneous features include: - Support for displaying the completion's documentation on a secondary popup; - Support for terminal display if :os tty; - Support for icons if +icons; - Support for tab-and-go completion if +tng; --- modules/completion/corfu/README.org | 139 +++++++++++++++++++ modules/completion/corfu/config.el | 192 +++++++++++++++++++++++++++ modules/completion/corfu/packages.el | 11 ++ modules/tools/lsp/+lsp.el | 5 +- 4 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 modules/completion/corfu/README.org create mode 100644 modules/completion/corfu/config.el create mode 100644 modules/completion/corfu/packages.el diff --git a/modules/completion/corfu/README.org b/modules/completion/corfu/README.org new file mode 100644 index 000000000..f98c13675 --- /dev/null +++ b/modules/completion/corfu/README.org @@ -0,0 +1,139 @@ +#+title: :completion corfu +#+subtitle: Complete with cap(f), cape and a flying feather +#+created: September 9, 2022 +#+since: 3.0.0 (#7002) + +* Description :unfold: +This module provides code completion, powered by [[doom-package:corfu]]. + +It is recommended to enable either this or [[doom-module::completion company]], in case you +desire pre-configured auto-completion. Corfu is much lighter weight and focused, +plus it's built on native Emacs functionality, whereas company is heavy and +highly non-native, but has some extra features and more maturity. + +** Maintainers +- [[doom-user:][@LuigiPiucco]] + +[[doom-contrib-maintainer:][Become a maintainer?]] + +** Module flags +- +icons :: + Display icons beside completion suggestions. +- +tng :: + Invoke completion on [[kbd:][TAB]]. When corfu is active, [[kbd:][TAB]] and [[kbd:][S-TAB]] will navigate + the completion candidates. Arrow keys and evil-style movement are still + supported. +- +orderless :: + Pull in [[doom-package:orderless]] if necessary and apply multi-component + completion (still needed if [[doom-module::completion vertico]] is active). + +** Packages +- [[doom-package:corfu]] +- [[doom-package:cape]] +- [[doom-package:nerd-icons-completion]] if [[doom-module::completion corfu +icons]] +- [[doom-package:orderless]] if [[doom-module::completion corfu +orderless]] +- [[doom-package:corfu-terminal]] if [[doom-module::os tty]] + +** Hacks +/No hacks documented for this module./ + +** TODO Changelog +# This section will be machine generated. Don't edit it by hand. +/This module does not have a changelog yet./ + +* Installation +Enable this module in your ~doom!~ block. + +This module has no direct requirements, but some languages may have their own +requirements to fulfill before you get code completion in them (and some +languages may lack code completion support altogether). Run ~$ doom doctor~ to +find out if you're missing any dependencies. Note that corfu may have support +for completions in languages that have no development intelligence, since it +supports generic, context insensitive candidates such as file names or recurring +words. + +* TODO Usage +#+begin_quote + 🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] +#+end_quote + +** Code completion +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 +is visible, the following relevant keys are available: + +| Keybind | Description | +|----------+------------------------------------------------------| +| [[kbd:][]] | Go to next candidate | +| [[kbd:][]] | Go to previous candidate | +| [[kbd:][C-n]] | Go to next candidate | +| [[kbd:][C-p]] | Go to previous candidate | +| [[kbd:][C-j]] | (evil) Go to next candidate | +| [[kbd:][C-k]] | (evil) Go to previous candidate | +| [[kbd:][C-]] | Go to next doc line | +| [[kbd:][C-]] | Go to previous doc line | +| [[kbd:][C-S-n]] | Go to next doc line | +| [[kbd:][C-S-p]] | Go to previous doc line | +| [[kbd:][C-S-j]] | (evil) Go to next doc line | +| [[kbd:][C-S-k]] | (evil) Go to previous doc line | +| [[kbd:][C-h]] | Toggle documentation (if available) | +| [[kbd:][s-]] | Export to minibuffer (if [[doom-module::completion vertico]]) | +| [[kbd:][s-j]] | (evil) Export to minibuffer (if [[doom-module::completion vertico]]) | +| [[kbd:][RET]] | Insert candidate | +| [[kbd:][C-SPC]] | (when completing) Insert separator (see below) | +| [[kbd:][C-SPC]] | Complete (unless [[doom-module::completion corfu +tng]]) | + +If you prefer a [[kbd:][TAB]]-centric completion style, enable the [[doom-module::completion corfu +tng]] +flag so that, instead, you trigger completion with [[kbd:][TAB]], getting the following +additional binds: + +| Keybind | Description | +|---------+--------------------------------------------| +| [[kbd:][TAB]] | Complete | +| [[kbd:][TAB]] | (when completing) Go to next candidate | +| [[kbd:][S-TAB]] | (when completing) Go to previous candidate | + +** Searching with multiple keywords +If the [[doom-module::completion corfu +orderless]] flag is enabled, users can +perform code completion with multiple search keywords by use of space as +separator. More information can be found [[https://github.com/oantolin/orderless#company][here]]. Pressing [[kdb:][C-SPC]] again while +completing inserts a space as separator. This allows searching with +space-separated terms; each piece will match individually and in any order, with +smart casing. Pressing just [[kbd:][SPC]] acts as normal and restarts completion, so that +when typing sentences it doesn't try to complete the whole sentence instead of +just the word. + +** Exporting to the minibuffer (requires [[doom-module::completion vertico]]) +When using the [[doom-module::completion vertico]] module, which pulls in the +[[doom-package:consult]] package, the entries shown in the completion popup can be +exported to a consult minibuffer, giving access to all the manipulations the +vertico suite allows. For instance, one could use this to export with +[[doom-package:embark]] via [[kbd:][C-c C-l]] and get a buffer with all candidates. + +* Configuration +A few variables may be set to change behavior of this module: + +- [[var:corfu-auto-delay]] :: + Number of seconds till completion occurs automatically. Defaults to 0.1. +- [[var:corfu-auto-prefix]] :: + Number of characters till auto-completion starts to happen. Defaults to 2. +- [[var:corfu-on-exact-match]] :: + Configures behavior for exact matches. Its default is nil, and it's + recommended to leave it at that. Otherwise, single matches on snippet keys + expand immediately. +- [[var:+corfu-completion-styles]] :: + Used to override [[var:completion-styles]] for corfu invocations, such that it + can have a value separate from, say, [[doom-package:consult]]. +- [[var:+corfu-icon-mapping]] :: + Configures icons used for each completion. See its documentation for details. + +* Troubleshooting +[[doom-report:][Report an issue?]] + +* Frequently asked questions +/This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]] + +* TODO Appendix +#+begin_quote + 🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] +#+end_quote diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el new file mode 100644 index 000000000..fad4c6dfc --- /dev/null +++ b/modules/completion/corfu/config.el @@ -0,0 +1,192 @@ +;;; completion/corfu/config.el -*- lexical-binding: t; -*- + +(defvar +corfu-completion-styles '(basic partial-completion flex) + "Completion styles for corfu to use. + +If the user enables +orderless, `orderless' is automatically appended to this +list before fowarding to `completion-styles'.") + +(defvar +corfu-icon-mapping + `((array ,(nerd-icons-codicon "nf-cod-symbol_array") :face font-lock-type-face) + (boolean ,(nerd-icons-codicon "nf-cod-symbol_boolean") :face font-lock-builtin-face) + (class ,(nerd-icons-codicon "nf-cod-symbol_class") :face font-lock-type-face) + (color ,(nerd-icons-codicon "nf-cod-symbol_color") :face success) + (command ,(nerd-icons-codicon "nf-cod-terminal") :face default) + (constant ,(nerd-icons-codicon "nf-cod-symbol_constant") :face font-lock-constant-face) + (constructor ,(nerd-icons-codicon "nf-cod-triangle_right") :face font-lock-function-name-face) + (enummember ,(nerd-icons-codicon "nf-cod-symbol_enum_member") :face font-lock-builtin-face) + (enum-member ,(nerd-icons-codicon "nf-cod-symbol_enum_member") :face font-lock-builtin-face) + (enum ,(nerd-icons-codicon "nf-cod-symbol_enum") :face font-lock-builtin-face) + (event ,(nerd-icons-codicon "nf-cod-symbol_event") :face font-lock-warning-face) + (field ,(nerd-icons-codicon "nf-cod-symbol_field") :face font-lock-variable-name-face) + (file ,(nerd-icons-codicon "nf-cod-symbol_file") :face font-lock-string-face) + (folder ,(nerd-icons-codicon "nf-cod-folder") :face font-lock-doc-face) + (interface ,(nerd-icons-codicon "nf-cod-symbol_interface") :face font-lock-type-face) + (keyword ,(nerd-icons-codicon "nf-cod-symbol_keyword") :face font-lock-keyword-face) + (macro ,(nerd-icons-codicon "nf-cod-symbol_misc") :face font-lock-keyword-face) + (magic ,(nerd-icons-codicon "nf-cod-wand") :face font-lock-builtin-face) + (method ,(nerd-icons-codicon "nf-cod-symbol_method") :face font-lock-function-name-face) + (function ,(nerd-icons-codicon "nf-cod-symbol_method") :face font-lock-function-name-face) + (module ,(nerd-icons-codicon "nf-cod-file_submodule") :face font-lock-preprocessor-face) + (numeric ,(nerd-icons-codicon "nf-cod-symbol_numeric") :face font-lock-builtin-face) + (operator ,(nerd-icons-codicon "nf-cod-symbol_operator") :face font-lock-comment-delimiter-face) + (param ,(nerd-icons-codicon "nf-cod-symbol_parameter") :face default) + (property ,(nerd-icons-codicon "nf-cod-symbol_property") :face font-lock-variable-name-face) + (reference ,(nerd-icons-codicon "nf-cod-references") :face font-lock-variable-name-face) + (snippet ,(nerd-icons-codicon "nf-cod-symbol_snippet") :face font-lock-string-face) + (string ,(nerd-icons-codicon "nf-cod-symbol_string") :face font-lock-string-face) + (struct ,(nerd-icons-codicon "nf-cod-symbol_structure") :face font-lock-variable-name-face) + (text ,(nerd-icons-codicon "nf-cod-text_size") :face font-lock-doc-face) + (typeparameter ,(nerd-icons-codicon "nf-cod-list_unordered") :face font-lock-type-face) + (type-parameter ,(nerd-icons-codicon "nf-cod-list_unordered") :face font-lock-type-face) + (unit ,(nerd-icons-codicon "nf-cod-symbol_ruler") :face font-lock-constant-face) + (value ,(nerd-icons-codicon "nf-cod-symbol_field") :face font-lock-builtin-face) + (variable ,(nerd-icons-codicon "nf-cod-symbol_variable") :face font-lock-variable-name-face) + (t ,(nerd-icons-codicon "nf-cod-code") :face font-lock-warning-face)) + "Mapping of completion kinds to icons. + +It should be a list of elements with the form (KIND ICON-TXT [:face FACE]). +KIND is a symbol determining what the completion is, and comes from calling the +`:company-kind' property of the completion. ICON-TXT is a string with the icon +to use, usually as a character from the `nerd-icons' symbol font. See that +package for how to get these. Note that it can be simple text if that is +preferred. FACE, if present, is applied to the icon, mainly for its color. The +special `t' symbol should be used for KIND to represent the default icon, and +must be present.") + +;; +;;; Packages +(use-package! corfu + :hook (doom-first-buffer . global-corfu-mode) + :hook (org-mode . corfu-mode) + :init + ;; Auto-completion settings, must be set before calling `global-corfu-mode'. + ;; Due to lazy-loading, setting them in config.el works too. + (setq corfu-auto t + corfu-auto-delay 0.1 + corfu-auto-prefix 2 + corfu-excluded-modes '(erc-mode + circe-mode + help-mode + gud-mode + vterm-mode)) + :config + (setq corfu-cycle t + corfu-separator (when (modulep! +orderless) ?\s) + corfu-preselect t + corfu-count 16 + corfu-max-width 120 + corfu-preview-current 'insert + corfu-on-exact-match nil + corfu-quit-at-boundary (if (modulep! +orderless) 'separator t) + corfu-quit-no-match (if (modulep! +orderless) 'separator t) + ;; In the case of +tng, TAB should be smart regarding completion; + ;; However, it should otherwise behave like normal, whatever normal was. + tab-always-indent (if (modulep! +tng) 'complete tab-always-indent)) + + (when (modulep! +orderless) + (after! 'lsp-mode + (add-to-list 'completion-category-overrides + `(lsp-capf (styles ,@+corfu-completion-styles ,(when (modulep! +orderless) 'orderless))))) + (after! 'eglot + (add-to-list 'completion-category-overrides + `(eglot (styles ,@+corfu-completion-styles ,(when (modulep! +orderless) 'orderless)))))) + + ;; For the icons, we use a custom margin formatter, which simply reads the + ;; mapping in `+corfu-icon-mapping'. + (when (modulep! +icons) + (defun icon-margin-formatter (metadata) + (when-let ((kindfunc (or (plist-get completion-extra-properties :company-kind) + (assq 'company-kind metadata)))) + (lambda (cand) + (let* ((kind (funcall kindfunc cand)) + (icon-entry (assq (or kind t) +corfu-icon-mapping)) + (str (cadr icon-entry)) + (props (cddr icon-entry)) + (extra-face (plist-get props :face)) + (space (propertize " " 'display '(space :width 1))) + (str (concat " " str space))) + (when extra-face + (put-text-property 0 3 'face extra-face str)) + str)))) + (setq corfu-margin-formatters '(icon-margin-formatter))) + + ;; This is to decouple the use of `completion-styles' in corfu from other + ;; completion packages, such as vertico. That way, the user can leave the + ;; global value of the variable alone, say, to be used by the default + ;; front-end or consult. The vertico module also does something similar with + ;; `+vertico-company-completion-styles'. + (defadvice! +corfu--completion-styles (orig &rest args) + "Try default completion styles before orderless. + +Meant as :around advice for `corfu--recompute'." + :around #'corfu--recompute + (let ((completion-styles + (append +corfu-completion-styles (when (modulep! +orderless) + '(orderless)))) + completion-category-overrides completion-category-defaults) + (apply orig args))) + + (map! (:unless (modulep! +tng) + "C-SPC" #'completion-at-point) + (:map 'corfu-map + (:when (modulep! +orderless) + "C-SPC" #'corfu-insert-separator) + (:when (modulep! +tng) + [tab] #'corfu-next + [backtab] #'corfu-previous + "TAB" #'corfu-next + "S-TAB" #'corfu-previous))) + (after! evil-collection-corfu + (evil-collection-define-key 'insert 'corfu-map + (kbd "RET") #'corfu-insert + [return] #'corfu-insert)) + + (after! vertico + ;; Taken from corfu's README. + ;; TODO: extend this to other completion front-ends. + (defun corfu-move-to-minibuffer () + (interactive) + (let ((completion-extra-properties corfu--extra) + (completion-cycle-threshold completion-cycling)) + (apply #'consult-completion-in-region completion-in-region--data))) + (map! :map 'corfu-map "s-" #'corfu-move-to-minibuffer + (:when (modulep! :editor evil) "s-j" #'corfu-move-to-minibuffer)))) + +(defmacro +corfu--add-capf! (capf) + "Create sexp to add CAPF to the list of CAPFs." + `(add-to-list 'completion-at-point-functions ,capf)) +(use-package! cape + :after corfu + :config + (add-hook! prog-mode (+corfu--add-capf! #'cape-file)) + (add-hook! (org-mode markdown-mode) (+corfu--add-capf! #'cape-elisp-block)) + (advice-add #'lsp-completion-at-point :around #'cape-wrap-noninterruptible)) + +(use-package! corfu-terminal + :when (not (display-graphic-p)) + :hook (corfu-mode . corfu-terminal-mode)) + +;; +;;; Extensions +(use-package! corfu-history + :after savehist + :hook (corfu-mode . corfu-history-mode) + :config + (add-to-list 'savehist-additional-variables 'corfu-history)) +(use-package! corfu-popupinfo + :hook (corfu-mode . corfu-popupinfo-mode) + :config + (setq corfu-popupinfo-delay '(0.5 . 1.0)) + (map! (:map 'corfu-map + "C-" #'corfu-popupinfo-scroll-down + "C-" #'corfu-popupinfo-scroll-up + "C-S-p" #'corfu-popupinfo-scroll-down + "C-S-n" #'corfu-popupinfo-scroll-up + "C-h" #'corfu-popupinfo-toggle) + (:map 'corfu-popupinfo-map + :when (modulep! :editor evil) + ;; Reversed because popupinfo assumes opposite of what feels intuitive + ;; with evil. + "C-S-k" #'corfu-popupinfo-scroll-down + "C-S-j" #'corfu-popupinfo-scroll-up))) diff --git a/modules/completion/corfu/packages.el b/modules/completion/corfu/packages.el new file mode 100644 index 000000000..7111813ae --- /dev/null +++ b/modules/completion/corfu/packages.el @@ -0,0 +1,11 @@ +;; -*- no-byte-compile: t; -*- +;;; completion/corfu/packages.el + +(package! corfu :recipe (:files ("*.el" "extensions/*.el"))) +(package! cape) +(when (modulep! +icons) + (package! nerd-icons-completion)) +(when (modulep! +orderless) + (package! orderless)) +(when (modulep! :os tty) + (package! corfu-terminal)) diff --git a/modules/tools/lsp/+lsp.el b/modules/tools/lsp/+lsp.el index 5ae4a417d..96361aae4 100644 --- a/modules/tools/lsp/+lsp.el +++ b/modules/tools/lsp/+lsp.el @@ -138,8 +138,11 @@ server getting expensively restarted when reverting buffers." " ")) (add-to-list 'global-mode-string '(t (:eval lsp-modeline-icon)) - 'append)))))) + 'append))))) + (when (modulep! :completion corfu) + (setq lsp-completion-provider :none) + (add-hook 'lsp-mode-hook #'lsp-completion-mode))) (use-package! lsp-ui :hook (lsp-mode . lsp-ui-mode) From 85f4c58a3ca5e33387b6713a0278f612dc9f28bf Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Mon, 24 Jul 2023 21:55:32 -0300 Subject: [PATCH 02/17] fix(corfu): pin packages --- modules/completion/corfu/packages.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/completion/corfu/packages.el b/modules/completion/corfu/packages.el index 7111813ae..7363ae0f9 100644 --- a/modules/completion/corfu/packages.el +++ b/modules/completion/corfu/packages.el @@ -1,11 +1,11 @@ ;; -*- no-byte-compile: t; -*- ;;; completion/corfu/packages.el -(package! corfu :recipe (:files ("*.el" "extensions/*.el"))) -(package! cape) +(package! corfu :recipe (:files ("*.el" "extensions/*.el")) :pin "b2b9a2312f58117514724e729fda43efc4433ecd") +(package! cape :pin "116063b9ee912cbaa7318dbe6597ade4a62b3f59") (when (modulep! +icons) - (package! nerd-icons-completion)) + (package! nerd-icons-completion :pin "c2db8557a3c1a9588d111f8c8e91cae96ee85010")) (when (modulep! +orderless) - (package! orderless)) + (package! orderless :pin "d6b402a89e234d0e6166247ed6025f9acc8b4d9a")) (when (modulep! :os tty) - (package! corfu-terminal)) + (package! corfu-terminal :pin "501548c3d51f926c687e8cd838c5865ec45d03cc")) From 787d040ba66fac86f309af95ff367589b5671a87 Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Wed, 26 Jul 2023 19:57:21 -0300 Subject: [PATCH 03/17] feat(corfu): add snippets Yasnippet is now properly integrated! A previosly-unset default has now been given to `corfu-on-exact-match`. With snippets, it causes immediate expansion upon single match by default, so we set it to nil and recommend against changing it in the README. --- modules/completion/corfu/README.org | 3 ++- modules/completion/corfu/config.el | 6 ++++++ modules/completion/corfu/packages.el | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/completion/corfu/README.org b/modules/completion/corfu/README.org index f98c13675..689855e81 100644 --- a/modules/completion/corfu/README.org +++ b/modules/completion/corfu/README.org @@ -33,6 +33,7 @@ highly non-native, but has some extra features and more maturity. - [[doom-package:nerd-icons-completion]] if [[doom-module::completion corfu +icons]] - [[doom-package:orderless]] if [[doom-module::completion corfu +orderless]] - [[doom-package:corfu-terminal]] if [[doom-module::os tty]] +- [[doom-package:yasnippet-capf]] if [[doom-module::editor snippets]] ** Hacks /No hacks documented for this module./ @@ -50,7 +51,7 @@ languages may lack code completion support altogether). Run ~$ doom doctor~ to find out if you're missing any dependencies. Note that corfu may have support for completions in languages that have no development intelligence, since it supports generic, context insensitive candidates such as file names or recurring -words. +words. Snippets may also appear in the candidate list if available. * TODO Usage #+begin_quote diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index fad4c6dfc..b1e38a844 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -163,6 +163,12 @@ Meant as :around advice for `corfu--recompute'." (add-hook! (org-mode markdown-mode) (+corfu--add-capf! #'cape-elisp-block)) (advice-add #'lsp-completion-at-point :around #'cape-wrap-noninterruptible)) +(use-package! yasnippet-capf + :after corfu + :config + (add-hook 'yas-minor-mode-hook + (lambda () (add-to-list 'completion-at-point-functions #'yasnippet-capf)))) + (use-package! corfu-terminal :when (not (display-graphic-p)) :hook (corfu-mode . corfu-terminal-mode)) diff --git a/modules/completion/corfu/packages.el b/modules/completion/corfu/packages.el index 7363ae0f9..b5a1b6bdb 100644 --- a/modules/completion/corfu/packages.el +++ b/modules/completion/corfu/packages.el @@ -9,3 +9,5 @@ (package! orderless :pin "d6b402a89e234d0e6166247ed6025f9acc8b4d9a")) (when (modulep! :os tty) (package! corfu-terminal :pin "501548c3d51f926c687e8cd838c5865ec45d03cc")) +(when (modulep! :editor snippets) + (package! yasnippet-capf :pin "40654214db7a44db3a99321447632b43a10fae57")) From bc00a4947543c0159a3d5e39750eb1b31e33963e Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Wed, 20 Sep 2023 10:54:28 -0300 Subject: [PATCH 04/17] docs(corfu): simplify and show how to add capfs --- modules/completion/corfu/README.org | 13 +++++++++++++ modules/completion/corfu/config.el | 7 ++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/modules/completion/corfu/README.org b/modules/completion/corfu/README.org index 689855e81..fd964833a 100644 --- a/modules/completion/corfu/README.org +++ b/modules/completion/corfu/README.org @@ -128,6 +128,19 @@ A few variables may be set to change behavior of this module: - [[var:+corfu-icon-mapping]] :: Configures icons used for each completion. See its documentation for details. +** Adding CAPFs to a mode +To add other CAPFs on a mode-per-mode basis, put either of the following in your +~config.el~: + +#+begin_src emacs-lisp +(add-hook! some-mode (add-to-list 'completion-at-point-functions #'some-capf)) +;; OR, but note the different call signature +(add-hook 'some-mode-hook (lambda () (add-to-list 'completion-at-point-functions #'some-capf))) +#+end_src + +Also see ~add-hook!~'s documentation for additional ways to call it. +~add-hook~ only accepts the quoted arguments form above. + * Troubleshooting [[doom-report:][Report an issue?]] diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index b1e38a844..150047911 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -153,14 +153,11 @@ Meant as :around advice for `corfu--recompute'." (map! :map 'corfu-map "s-" #'corfu-move-to-minibuffer (:when (modulep! :editor evil) "s-j" #'corfu-move-to-minibuffer)))) -(defmacro +corfu--add-capf! (capf) - "Create sexp to add CAPF to the list of CAPFs." - `(add-to-list 'completion-at-point-functions ,capf)) (use-package! cape :after corfu :config - (add-hook! prog-mode (+corfu--add-capf! #'cape-file)) - (add-hook! (org-mode markdown-mode) (+corfu--add-capf! #'cape-elisp-block)) + (add-hook! prog-mode (add-to-list 'completion-at-point-functions #'cape-file)) + (add-hook! (org-mode markdown-mode) (add-to-list 'completion-at-point-functions #'cape-elisp-block)) (advice-add #'lsp-completion-at-point :around #'cape-wrap-noninterruptible)) (use-package! yasnippet-capf From 2d62db15c4ec78842303c23f824be57a1daf98e4 Mon Sep 17 00:00:00 2001 From: Liam Hupfer Date: Sun, 24 Sep 2023 15:28:45 -0500 Subject: [PATCH 05/17] perf(corfu): improve lazy loading `:after y` eagerly loads package x after y loads. Cape and `yasnippet-capf` define autoloads, so we can defer them until a capf is actually called. --- modules/completion/corfu/config.el | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index 150047911..6833afb56 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -61,7 +61,7 @@ must be present.") :hook (org-mode . corfu-mode) :init ;; Auto-completion settings, must be set before calling `global-corfu-mode'. - ;; Due to lazy-loading, setting them in config.el works too. + ;; Due to lazy-loading, overriding these in config.el works too. (setq corfu-auto t corfu-auto-delay 0.1 corfu-auto-prefix 2 @@ -154,17 +154,19 @@ Meant as :around advice for `corfu--recompute'." (:when (modulep! :editor evil) "s-j" #'corfu-move-to-minibuffer)))) (use-package! cape - :after corfu - :config + :defer t + :init (add-hook! prog-mode (add-to-list 'completion-at-point-functions #'cape-file)) (add-hook! (org-mode markdown-mode) (add-to-list 'completion-at-point-functions #'cape-elisp-block)) (advice-add #'lsp-completion-at-point :around #'cape-wrap-noninterruptible)) (use-package! yasnippet-capf - :after corfu - :config - (add-hook 'yas-minor-mode-hook - (lambda () (add-to-list 'completion-at-point-functions #'yasnippet-capf)))) + :when (modulep! :editor snippets) + :defer t + :init + (after! yasnippet + (add-hook! yas-minor-mode + (add-to-list 'completion-at-point-functions #'yasnippet-capf)))) (use-package! corfu-terminal :when (not (display-graphic-p)) From 4d118ff01e401f3ee5e0cc4ec8d71fff1d581427 Mon Sep 17 00:00:00 2001 From: Liam Hupfer Date: Sun, 24 Sep 2023 15:29:06 -0500 Subject: [PATCH 06/17] tweak(corfu): allow corfu-history without savehist savehist is for persisting history across sessions, but users who disable savehist can still benefit from session-length Corfu history. --- modules/completion/corfu/config.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index 6833afb56..f115e343e 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -172,13 +172,14 @@ Meant as :around advice for `corfu--recompute'." :when (not (display-graphic-p)) :hook (corfu-mode . corfu-terminal-mode)) -;; ;;; Extensions + (use-package! corfu-history - :after savehist :hook (corfu-mode . corfu-history-mode) :config - (add-to-list 'savehist-additional-variables 'corfu-history)) + (after! savehist (add-to-list 'savehist-additional-variables 'corfu-history))) + + (use-package! corfu-popupinfo :hook (corfu-mode . corfu-popupinfo-mode) :config From 61c3b74231916cf3c3c4c36a90e4f407a02a1a28 Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Mon, 2 Oct 2023 13:11:19 -0300 Subject: [PATCH 07/17] tweak(corfu): use better binding instead of S- --- modules/completion/corfu/config.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index f115e343e..3054b2905 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -150,8 +150,8 @@ Meant as :around advice for `corfu--recompute'." (let ((completion-extra-properties corfu--extra) (completion-cycle-threshold completion-cycling)) (apply #'consult-completion-in-region completion-in-region--data))) - (map! :map 'corfu-map "s-" #'corfu-move-to-minibuffer - (:when (modulep! :editor evil) "s-j" #'corfu-move-to-minibuffer)))) + (map! :map 'corfu-map "M-m" #'corfu-move-to-minibuffer + (:when (modulep! :editor evil) :i "M-j" #'corfu-move-to-minibuffer)))) (use-package! cape :defer t From 5c1e1978d5e77cd45000bd42c3949ca28c7994ec Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Mon, 2 Oct 2023 13:13:23 -0300 Subject: [PATCH 08/17] tweak(corfu): quit corfu on evil quit --- modules/completion/corfu/config.el | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index 3054b2905..8c990b343 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -85,13 +85,16 @@ must be present.") tab-always-indent (if (modulep! +tng) 'complete tab-always-indent)) (when (modulep! +orderless) - (after! 'lsp-mode + (after! lsp-mode (add-to-list 'completion-category-overrides `(lsp-capf (styles ,@+corfu-completion-styles ,(when (modulep! +orderless) 'orderless))))) - (after! 'eglot + (after! eglot (add-to-list 'completion-category-overrides `(eglot (styles ,@+corfu-completion-styles ,(when (modulep! +orderless) 'orderless)))))) + (after! evil + (add-hook 'evil-insert-state-exit-hook #'corfu-quit)) + ;; For the icons, we use a custom margin formatter, which simply reads the ;; mapping in `+corfu-icon-mapping'. (when (modulep! +icons) From 61c73c9def048659ec8c0c7adbdb86fc159ed5ba Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Sun, 15 Oct 2023 14:59:12 -0300 Subject: [PATCH 09/17] feat(corfu): switch to nerd-icons-corfu This removes the need to vendor the icon code. --- modules/completion/corfu/README.org | 3 +- modules/completion/corfu/config.el | 67 +--------------------------- modules/completion/corfu/packages.el | 3 +- 3 files changed, 5 insertions(+), 68 deletions(-) diff --git a/modules/completion/corfu/README.org b/modules/completion/corfu/README.org index fd964833a..1f071b638 100644 --- a/modules/completion/corfu/README.org +++ b/modules/completion/corfu/README.org @@ -31,6 +31,7 @@ highly non-native, but has some extra features and more maturity. - [[doom-package:corfu]] - [[doom-package:cape]] - [[doom-package:nerd-icons-completion]] if [[doom-module::completion corfu +icons]] +- [[doom-package:nerd-icons-corfu]] if [[doom-module::completion corfu +icons]] - [[doom-package:orderless]] if [[doom-module::completion corfu +orderless]] - [[doom-package:corfu-terminal]] if [[doom-module::os tty]] - [[doom-package:yasnippet-capf]] if [[doom-module::editor snippets]] @@ -125,8 +126,6 @@ A few variables may be set to change behavior of this module: - [[var:+corfu-completion-styles]] :: Used to override [[var:completion-styles]] for corfu invocations, such that it can have a value separate from, say, [[doom-package:consult]]. -- [[var:+corfu-icon-mapping]] :: - Configures icons used for each completion. See its documentation for details. ** Adding CAPFs to a mode To add other CAPFs on a mode-per-mode basis, put either of the following in your diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index 8c990b343..a36685ed9 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -6,54 +6,6 @@ If the user enables +orderless, `orderless' is automatically appended to this list before fowarding to `completion-styles'.") -(defvar +corfu-icon-mapping - `((array ,(nerd-icons-codicon "nf-cod-symbol_array") :face font-lock-type-face) - (boolean ,(nerd-icons-codicon "nf-cod-symbol_boolean") :face font-lock-builtin-face) - (class ,(nerd-icons-codicon "nf-cod-symbol_class") :face font-lock-type-face) - (color ,(nerd-icons-codicon "nf-cod-symbol_color") :face success) - (command ,(nerd-icons-codicon "nf-cod-terminal") :face default) - (constant ,(nerd-icons-codicon "nf-cod-symbol_constant") :face font-lock-constant-face) - (constructor ,(nerd-icons-codicon "nf-cod-triangle_right") :face font-lock-function-name-face) - (enummember ,(nerd-icons-codicon "nf-cod-symbol_enum_member") :face font-lock-builtin-face) - (enum-member ,(nerd-icons-codicon "nf-cod-symbol_enum_member") :face font-lock-builtin-face) - (enum ,(nerd-icons-codicon "nf-cod-symbol_enum") :face font-lock-builtin-face) - (event ,(nerd-icons-codicon "nf-cod-symbol_event") :face font-lock-warning-face) - (field ,(nerd-icons-codicon "nf-cod-symbol_field") :face font-lock-variable-name-face) - (file ,(nerd-icons-codicon "nf-cod-symbol_file") :face font-lock-string-face) - (folder ,(nerd-icons-codicon "nf-cod-folder") :face font-lock-doc-face) - (interface ,(nerd-icons-codicon "nf-cod-symbol_interface") :face font-lock-type-face) - (keyword ,(nerd-icons-codicon "nf-cod-symbol_keyword") :face font-lock-keyword-face) - (macro ,(nerd-icons-codicon "nf-cod-symbol_misc") :face font-lock-keyword-face) - (magic ,(nerd-icons-codicon "nf-cod-wand") :face font-lock-builtin-face) - (method ,(nerd-icons-codicon "nf-cod-symbol_method") :face font-lock-function-name-face) - (function ,(nerd-icons-codicon "nf-cod-symbol_method") :face font-lock-function-name-face) - (module ,(nerd-icons-codicon "nf-cod-file_submodule") :face font-lock-preprocessor-face) - (numeric ,(nerd-icons-codicon "nf-cod-symbol_numeric") :face font-lock-builtin-face) - (operator ,(nerd-icons-codicon "nf-cod-symbol_operator") :face font-lock-comment-delimiter-face) - (param ,(nerd-icons-codicon "nf-cod-symbol_parameter") :face default) - (property ,(nerd-icons-codicon "nf-cod-symbol_property") :face font-lock-variable-name-face) - (reference ,(nerd-icons-codicon "nf-cod-references") :face font-lock-variable-name-face) - (snippet ,(nerd-icons-codicon "nf-cod-symbol_snippet") :face font-lock-string-face) - (string ,(nerd-icons-codicon "nf-cod-symbol_string") :face font-lock-string-face) - (struct ,(nerd-icons-codicon "nf-cod-symbol_structure") :face font-lock-variable-name-face) - (text ,(nerd-icons-codicon "nf-cod-text_size") :face font-lock-doc-face) - (typeparameter ,(nerd-icons-codicon "nf-cod-list_unordered") :face font-lock-type-face) - (type-parameter ,(nerd-icons-codicon "nf-cod-list_unordered") :face font-lock-type-face) - (unit ,(nerd-icons-codicon "nf-cod-symbol_ruler") :face font-lock-constant-face) - (value ,(nerd-icons-codicon "nf-cod-symbol_field") :face font-lock-builtin-face) - (variable ,(nerd-icons-codicon "nf-cod-symbol_variable") :face font-lock-variable-name-face) - (t ,(nerd-icons-codicon "nf-cod-code") :face font-lock-warning-face)) - "Mapping of completion kinds to icons. - -It should be a list of elements with the form (KIND ICON-TXT [:face FACE]). -KIND is a symbol determining what the completion is, and comes from calling the -`:company-kind' property of the completion. ICON-TXT is a string with the icon -to use, usually as a character from the `nerd-icons' symbol font. See that -package for how to get these. Note that it can be simple text if that is -preferred. FACE, if present, is applied to the icon, mainly for its color. The -special `t' symbol should be used for KIND to represent the default icon, and -must be present.") - ;; ;;; Packages (use-package! corfu @@ -95,24 +47,8 @@ must be present.") (after! evil (add-hook 'evil-insert-state-exit-hook #'corfu-quit)) - ;; For the icons, we use a custom margin formatter, which simply reads the - ;; mapping in `+corfu-icon-mapping'. (when (modulep! +icons) - (defun icon-margin-formatter (metadata) - (when-let ((kindfunc (or (plist-get completion-extra-properties :company-kind) - (assq 'company-kind metadata)))) - (lambda (cand) - (let* ((kind (funcall kindfunc cand)) - (icon-entry (assq (or kind t) +corfu-icon-mapping)) - (str (cadr icon-entry)) - (props (cddr icon-entry)) - (extra-face (plist-get props :face)) - (space (propertize " " 'display '(space :width 1))) - (str (concat " " str space))) - (when extra-face - (put-text-property 0 3 'face extra-face str)) - str)))) - (setq corfu-margin-formatters '(icon-margin-formatter))) + (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) ;; This is to decouple the use of `completion-styles' in corfu from other ;; completion packages, such as vertico. That way, the user can leave the @@ -175,6 +111,7 @@ Meant as :around advice for `corfu--recompute'." :when (not (display-graphic-p)) :hook (corfu-mode . corfu-terminal-mode)) +;; ;;; Extensions (use-package! corfu-history diff --git a/modules/completion/corfu/packages.el b/modules/completion/corfu/packages.el index b5a1b6bdb..1d9f48f6c 100644 --- a/modules/completion/corfu/packages.el +++ b/modules/completion/corfu/packages.el @@ -4,7 +4,8 @@ (package! corfu :recipe (:files ("*.el" "extensions/*.el")) :pin "b2b9a2312f58117514724e729fda43efc4433ecd") (package! cape :pin "116063b9ee912cbaa7318dbe6597ade4a62b3f59") (when (modulep! +icons) - (package! nerd-icons-completion :pin "c2db8557a3c1a9588d111f8c8e91cae96ee85010")) + (package! nerd-icons-completion :pin "c2db8557a3c1a9588d111f8c8e91cae96ee85010") + (package! nerd-icons-corfu :pin "5082a22dfbdea092fcc475db3484cb3ff812b730")) (when (modulep! +orderless) (package! orderless :pin "d6b402a89e234d0e6166247ed6025f9acc8b4d9a")) (when (modulep! :os tty) From 50bdf024ada178683913881bf01a999ec2a2895f Mon Sep 17 00:00:00 2001 From: StrawberryTea Date: Mon, 30 Oct 2023 14:36:19 -0400 Subject: [PATCH 10/17] feat(corfu): more CAPFs and ergonomy changes Add various CAPFs from cape: - `cape-line`; - `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 `backspace` for `+tng`; - Smart `DEL` for `+tng`; - Smart `SPC` which quits if after separator; - Smart `RET`; Add depth to CAPFs, allowing ordering to be adjustable. Remove the `+corfu-completion-styles` mechanism. Add `,` as additional separator. Enable in minibuffer. Bump `cape`. --- modules/completion/corfu/README.org | 101 ++++++---- modules/completion/corfu/autoload.el | 18 ++ modules/completion/corfu/config.el | 265 +++++++++++++++++++++------ modules/completion/corfu/packages.el | 2 +- 4 files changed, 291 insertions(+), 95 deletions(-) create mode 100644 modules/completion/corfu/autoload.el diff --git a/modules/completion/corfu/README.org b/modules/completion/corfu/README.org index 1f071b638..e74332d16 100644 --- a/modules/completion/corfu/README.org +++ b/modules/completion/corfu/README.org @@ -64,46 +64,51 @@ 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 is visible, the following relevant keys are available: -| Keybind | Description | -|----------+------------------------------------------------------| -| [[kbd:][]] | Go to next candidate | -| [[kbd:][]] | Go to previous candidate | -| [[kbd:][C-n]] | Go to next candidate | -| [[kbd:][C-p]] | Go to previous candidate | -| [[kbd:][C-j]] | (evil) Go to next candidate | -| [[kbd:][C-k]] | (evil) Go to previous candidate | -| [[kbd:][C-]] | Go to next doc line | -| [[kbd:][C-]] | Go to previous doc line | -| [[kbd:][C-S-n]] | Go to next doc line | -| [[kbd:][C-S-p]] | Go to previous doc line | -| [[kbd:][C-S-j]] | (evil) Go to next doc line | -| [[kbd:][C-S-k]] | (evil) Go to previous doc line | -| [[kbd:][C-h]] | Toggle documentation (if available) | -| [[kbd:][s-]] | Export to minibuffer (if [[doom-module::completion vertico]]) | -| [[kbd:][s-j]] | (evil) Export to minibuffer (if [[doom-module::completion vertico]]) | -| [[kbd:][RET]] | Insert candidate | -| [[kbd:][C-SPC]] | (when completing) Insert separator (see below) | -| [[kbd:][C-SPC]] | Complete (unless [[doom-module::completion corfu +tng]]) | +| Keybind | Description | +|----------+---------------------------------------------------------| +| [[kbd:][]] | Go to next candidate | +| [[kbd:][]] | Go to previous candidate | +| [[kbd:][C-n]] | Go to next candidate | +| [[kbd:][C-p]] | Go to previous candidate | +| [[kbd:][C-j]] | (evil) Go to next candidate | +| [[kbd:][C-k]] | (evil) Go to previous candidate | +| [[kbd:][C-]] | Go to next doc line | +| [[kbd:][C-]] | Go to previous doc line | +| [[kbd:][C-S-n]] | Go to next doc line | +| [[kbd:][C-S-p]] | Go to previous doc line | +| [[kbd:][C-S-j]] | (evil) Go to next doc line | +| [[kbd:][C-S-k]] | (evil) Go to previous doc line | +| [[kbd:][C-h]] | Toggle documentation (if available) | +| [[kbd:][M-m]] | 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:][SPC]] | Quit autocompletion after a wildcard or pass-through | +| [[kbd:][C-SPC]] | (when completing) Insert separator (see below) | +| [[kbd:][C-SPC]] | Complete (unless [[doom-module::completion corfu +tng]]) | If you prefer a [[kbd:][TAB]]-centric completion style, enable the [[doom-module::completion corfu +tng]] flag so that, instead, you trigger completion with [[kbd:][TAB]], getting the following additional binds: -| Keybind | Description | -|---------+--------------------------------------------| -| [[kbd:][TAB]] | Complete | -| [[kbd:][TAB]] | (when completing) Go to next candidate | -| [[kbd:][S-TAB]] | (when completing) Go to previous candidate | +| Keybind | Description | +|---------+-----------------------------------------------| +| [[kbd:][TAB]] | Complete | +| [[kbd:][TAB]] | (when completing) Go to next candidate | +| [[kbd:][S-TAB]] | (when completing) Go to previous candidate | +| [[kbd:][DEL]] | (when completing) Reset completion DWIM-style | ** Searching with multiple keywords -If the [[doom-module::completion corfu +orderless]] flag is enabled, users can -perform code completion with multiple search keywords by use of space as -separator. More information can be found [[https://github.com/oantolin/orderless#company][here]]. Pressing [[kdb:][C-SPC]] again while -completing inserts a space as separator. This allows searching with -space-separated terms; each piece will match individually and in any order, with -smart casing. Pressing just [[kbd:][SPC]] acts as normal and restarts completion, so that -when typing sentences it doesn't try to complete the whole sentence instead of -just the word. +If the [[doom-module::completion corfu +orderless]] flag is enabled, users can perform code +completion with multiple search keywords by use of space as the separator. More +information can be found [[https://github.com/oantolin/orderless#company][here]]. Pressing [[kdb:][C-SPC]] again while completing inserts a +space as separator. This allows searching with space-separated terms; each piece +will match individually and in any order, with smart casing. Pressing just [[kbd:][SPC]] +acts as normal and restarts completion, so that when typing sentences it doesn't +try to complete the whole sentence instead of just the word. + +Furthermore, if you also have [[var:+orderless-wildcard-character]] set (by default +it's the comma key), then that character acts as a wildcard when typed +mid-completion. ** Exporting to the minibuffer (requires [[doom-module::completion vertico]]) When using the [[doom-module::completion vertico]] module, which pulls in the @@ -123,26 +128,42 @@ A few variables may be set to change behavior of this module: Configures behavior for exact matches. Its default is nil, and it's recommended to leave it at that. Otherwise, single matches on snippet keys expand immediately. -- [[var:+corfu-completion-styles]] :: - Used to override [[var:completion-styles]] for corfu invocations, such that it - can have a value separate from, say, [[doom-package:consult]]. +- [[var:+orderless-wildcard-character]] :: + Used for fuzzy-matching corfu invocations as an escapable alternative to + ~corfu-separator~. Defaults to comma. +- [[var:+cape-buffer-scanning-size-limit:]] :: + Sets the maximum buffer size to be scanned by ~cape-dabbrev~ and + ~cape-lines~. Defaults to 1 MB. Set this if you are having performance + problems using ~cape-dabbrev~. ** Adding CAPFs to a mode To add other CAPFs on a mode-per-mode basis, put either of the following in your ~config.el~: #+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 -(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 -Also see ~add-hook!~'s documentation for additional ways to call it. -~add-hook~ only accepts the quoted arguments form above. +DEPTH above is an integer between -100, 100, and defaults to 0 of ommited. Also +see ~add-hook!~'s documentation for additional ways to call it. ~add-hook~ only +accepts the quoted arguments form above. * Troubleshooting [[doom-report:][Report an issue?]] +If you have performance issues with ~cape-dabbrev~, the first thing I recommend +doing is looking at the list of buffers Dabbrev is scanning with: + +#+begin_src emacs-lisp +(dabbrev--select-buffers) ; => (# #> # ...) +(length (dabbrev--select-buffers)) ; => 37 +#+end_src + +and modifying ~dabbrev-ignored-buffer-regexps~ or ~dabbrev-ignored-buffer-modes~ +accordingly. + * Frequently asked questions /This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]] diff --git a/modules/completion/corfu/autoload.el b/modules/completion/corfu/autoload.el new file mode 100644 index 000000000..215e5bd41 --- /dev/null +++ b/modules/completion/corfu/autoload.el @@ -0,0 +1,18 @@ +;;; completion/corfu/autoload/commands.el -*- lexical-binding: t; -*- + +;;;###autoload +(defun corfu-move-to-minibuffer () + ;; Taken from corfu's README. + ;; TODO: extend this to other completion front-ends. + (interactive) + (let ((completion-extra-properties corfu--extra) + (completion-cycle-threshold completion-cycling)) + (apply #'consult-completion-in-region completion-in-region--data))) + +;;;###autoload +(defun +corfu-insert-wildcard-separator () + ;; I had to rename this command so that it doesn't start with "corfu-". + ;; Otherwise, it does not insert the completion when +tng is enabled. + (interactive) + (setq this-command #'corfu-insert-separator) + (call-interactively #'corfu-insert-separator)) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index a36685ed9..d558f8e9e 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -1,10 +1,17 @@ ;;; completion/corfu/config.el -*- lexical-binding: t; -*- -(defvar +corfu-completion-styles '(basic partial-completion flex) - "Completion styles for corfu to use. +(defvar +cape-buffer-scanning-size-limit (* 1 1024 1024) ; 1 MB + "Size limit for a buffer to be scanned by `cape-line' or `cape-dabbrev'. -If the user enables +orderless, `orderless' is automatically appended to this -list before fowarding to `completion-styles'.") +As an exception, `cape-line' will also scan buffers with the same +major mode regardless of size.") + +(defvar +orderless-wildcard-character ?, + "A character used as a wildcard in Corfu for fuzzy autocompletion. If you +want to match the wildcard literally in completion, you can +escape it with forward slash. Do NOT set this to SPC. + +This variable needs to be set at the top-level before any `after!' blocks.") ;; ;;; Packages @@ -22,10 +29,12 @@ list before fowarding to `completion-styles'.") help-mode gud-mode vterm-mode)) + ;; `:g' is needed here to prevent `global-map' from overriding this with + ;; `set-mark-command'. + (map! :unless (modulep! +tng) :gi "C-SPC" #'completion-at-point) :config (setq corfu-cycle t - corfu-separator (when (modulep! +orderless) ?\s) - corfu-preselect t + corfu-preselect (if (modulep! :completion corfu +tng) 'prompt t) corfu-count 16 corfu-max-width 120 corfu-preview-current 'insert @@ -36,76 +45,224 @@ list before fowarding to `completion-styles'.") ;; However, it should otherwise behave like normal, whatever normal was. tab-always-indent (if (modulep! +tng) 'complete tab-always-indent)) - (when (modulep! +orderless) - (after! lsp-mode - (add-to-list 'completion-category-overrides - `(lsp-capf (styles ,@+corfu-completion-styles ,(when (modulep! +orderless) 'orderless))))) - (after! eglot - (add-to-list 'completion-category-overrides - `(eglot (styles ,@+corfu-completion-styles ,(when (modulep! +orderless) 'orderless)))))) + (defun corfu-disable-in-minibuffer-p () + (or (bound-and-true-p mct--active) + (bound-and-true-p vertico--input) + (and (featurep 'helm-core) (helm--alive-p)) + (eq (current-local-map) read-passwd-map))) - (after! evil - (add-hook 'evil-insert-state-exit-hook #'corfu-quit)) + (defun corfu-enable-in-minibuffer () + "Enable Corfu in the minibuffer if `completion-at-point' is bound." + (unless (corfu-disable-in-minibuffer-p) + (setq-local corfu-echo-delay nil ;; Disable automatic echo and popup + corfu-popupinfo-delay nil) + (corfu-mode 1))) + + (add-hook 'minibuffer-setup-hook #'corfu-enable-in-minibuffer) + + (defun corfu-visible-p () + (or (and (frame-live-p corfu--frame) + (frame-visible-p corfu--frame)) + (and (featurep 'corfu-terminal) + (popon-live-p corfu-terminal--popon)))) + + ;; If you want to update the visual hints after completing minibuffer commands + ;; with Corfu and exiting, you have to do it manually. + (defadvice! +corfu--insert-before-exit-minibuffer-a () + :before #'exit-minibuffer + (when (corfu-visible-p) + (when (member isearch-lazy-highlight-timer timer-idle-list) + (apply (timer--function isearch-lazy-highlight-timer) + (timer--args isearch-lazy-highlight-timer))) + (when (member (bound-and-true-p anzu--update-timer) timer-idle-list) + ;; Pending a PR I (@LemonBreezes) am making to expose `anzu--update-timer'. + (apply (timer--function anzu--update-timer) + (timer--args anzu--update-timer))) + (when (member (bound-and-true-p evil--ex-search-update-timer) + timer-idle-list) + (apply (timer--function evil--ex-search-update-timer) + (timer--args evil--ex-search-update-timer))))) + + ;; Do not make us type RET twice with Corfu. + (defun corfu--maybe-return-filter (cmd) + (if (eq corfu--index -1) (corfu-quit) cmd)) + (keymap-set corfu-map "RET" `(menu-item "corfu-maybe-return" corfu-insert + :filter corfu--maybe-return-filter)) + (keymap-set + corfu-map "" `(menu-item "corfu-maybe-return" corfu-insert + :filter corfu--maybe-return-filter)) + + ;; Allow completion after `:' in Lispy. + (add-to-list 'corfu-auto-commands #'lispy-colon) + + (when (and (modulep! +orderless) + +orderless-wildcard-character) + (defmacro +orderless-escapable-split-fn (char) + (let ((char-string (string (if (symbolp char) (symbol-value char) char)))) + `(defun +orderless-escapable-split-on-space-or-char (s) + (mapcar + (lambda (piece) + (replace-regexp-in-string + (string 1) ,char-string + (replace-regexp-in-string + (concat (string 0) "\\|" (string 1)) + (lambda (x) + (pcase x + ("\0" " ") + ("\1" ,char-string) + (_ x))) + piece + ;; These are arguments to `replace-regexp-in-string'. + 'fixedcase 'literal) + 'fixedcase 'literal)) + (split-string (replace-regexp-in-string + (concat "\\\\\\\\\\|\\\\ \\|\\\\" + ,char-string) + (lambda (x) + (pcase x + ("\\ " "\0") + (,(concat "\\" char-string) + "\1") + (_ x))) + s 'fixedcase 'literal) + ,(concat "[ " char-string "]+") + t))))) + (after! orderless + ;; Orderless splits the string into components and then determines the + ;; matching style for each component. This is all regexp stuff. + (setq orderless-component-separator + (+orderless-escapable-split-fn +orderless-wildcard-character)) + (setq corfu-separator +orderless-wildcard-character) + (keymap-set corfu-map (char-to-string +orderless-wildcard-character) + #'+corfu-insert-wildcard-separator) + ;; Quit completion after typing the wildcard followed by a space. + (keymap-set corfu-map "SPC" + `(menu-item "corfu-maybe-quit" nil + :filter + ,(lambda (_) + (when (and (> (point) (point-min)) + (eq (char-before) + +orderless-wildcard-character)) + (corfu-quit) + nil)))))) + + (add-hook! 'evil-insert-state-exit-hook + (defun +corfu-quit-on-evil-insert-state-exit-h () + ;; This predicate a workaround for unexpected calls to `corfu-quit' in + ;; :company-doc-buffer buffers. This was specifically happening when using + ;; `yasnippet-capf' and `company-yasnippet'. + (when (eq (current-buffer) (window-buffer (selected-window))) + (corfu-quit)))) (when (modulep! +icons) (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) - ;; This is to decouple the use of `completion-styles' in corfu from other - ;; completion packages, such as vertico. That way, the user can leave the - ;; global value of the variable alone, say, to be used by the default - ;; front-end or consult. The vertico module also does something similar with - ;; `+vertico-company-completion-styles'. - (defadvice! +corfu--completion-styles (orig &rest args) - "Try default completion styles before orderless. + ;; Reset completion DWIM-style with backspace. + (when (modulep! +tng) + (defun corfu--maybe-reset-backspace-filter (cmd) + (when (and (> corfu--index -1) + (eq corfu-preview-current 'insert)) + cmd)) + (keymap-set corfu-map "DEL" `(menu-item "corfu-maybe-reset" corfu-reset + :filter corfu--maybe-reset-backspace-filter)) + (keymap-set + corfu-map "" `(menu-item "corfu-maybe-reset" corfu-reset + :filter corfu--maybe-reset-backspace-filter))) -Meant as :around advice for `corfu--recompute'." - :around #'corfu--recompute - (let ((completion-styles - (append +corfu-completion-styles (when (modulep! +orderless) - '(orderless)))) - completion-category-overrides completion-category-defaults) - (apply orig args))) - - (map! (:unless (modulep! +tng) - "C-SPC" #'completion-at-point) - (:map 'corfu-map - (:when (modulep! +orderless) - "C-SPC" #'corfu-insert-separator) - (:when (modulep! +tng) - [tab] #'corfu-next - [backtab] #'corfu-previous - "TAB" #'corfu-next - "S-TAB" #'corfu-previous))) + (map! (:map 'corfu-map + (:when (modulep! +orderless) + :gi "C-SPC" #'corfu-insert-separator) + (:when (modulep! +tng) + [tab] #'corfu-next + [backtab] #'corfu-previous + "TAB" #'corfu-next + "S-TAB" #'corfu-previous))) (after! evil-collection-corfu (evil-collection-define-key 'insert 'corfu-map (kbd "RET") #'corfu-insert [return] #'corfu-insert)) (after! vertico - ;; Taken from corfu's README. - ;; TODO: extend this to other completion front-ends. - (defun corfu-move-to-minibuffer () - (interactive) - (let ((completion-extra-properties corfu--extra) - (completion-cycle-threshold completion-cycling)) - (apply #'consult-completion-in-region completion-in-region--data))) - (map! :map 'corfu-map "M-m" #'corfu-move-to-minibuffer - (:when (modulep! :editor evil) :i "M-j" #'corfu-move-to-minibuffer)))) + (map! :map 'corfu-map "M-m" #'corfu-move-to-minibuffer) + (after! evil-collection-corfu + (evil-collection-define-key 'insert 'corfu-map + (kbd "M-j") #'corfu-move-to-minibuffer)))) (use-package! cape :defer t :init - (add-hook! prog-mode (add-to-list 'completion-at-point-functions #'cape-file)) - (add-hook! (org-mode markdown-mode) (add-to-list 'completion-at-point-functions #'cape-elisp-block)) + ;; Set up `cape-dabbrev' and `cape-line' options. + (defun +cape-line-buffers () + (cl-loop for buf in (buffer-list) + if (or (eq major-mode (buffer-local-value 'major-mode buf)) + (< (buffer-size buf) +cape-buffer-scanning-size-limit)) + collect buf)) + (defun +dabbrev-friend-buffer-p (other-buffer) + (< (buffer-size other-buffer) +cape-buffer-scanning-size-limit)) + (setq cape-dabbrev-check-other-buffers t + cape-line-buffer-function #'+cape-line-buffers + dabbrev-friend-buffer-function #'+dabbrev-friend-buffer-p + dabbrev-ignored-buffer-regexps + '("\\.\\(?:pdf\\|jpe?g\\|png\\|svg\\|eps\\)\\'" + "^ " + "\\(TAGS\\|tags\\|ETAGS\\|etags\\|GTAGS\\|GRTAGS\\|GPATH\\)\\(<[0-9]+>\\)?") + dabbrev-upcase-means-case-search t) + + (add-hook! prog-mode + (add-hook 'completion-at-point-functions #'cape-file -10 t)) + (add-hook! (org-mode markdown-mode) + (add-hook 'completion-at-point-functions #'cape-elisp-block 0 t)) + + ;; Enable Dabbrev completion basically everywhere as a fallback. + (add-hook! (prog-mode text-mode conf-mode comint-mode minibuffer-setup + eshell-mode) + (add-hook 'completion-at-point-functions #'cape-dabbrev 20 t)) + + ;; Complete emojis :). + (when (> emacs-major-version 28) + (add-hook! (prog-mode conf-mode) + (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 + (add-hook 'completion-at-point-functions + (cape-capf-prefix-length #'cape-emoji 1) 10 t))) + + ;; Enable dictionary-based autocompletion. + (add-hook! text-mode + (add-hook 'completion-at-point-functions #'cape-dict 40 t)) + (add-hook! (prog-mode conf-mode) + (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)) + + ;; 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)) (use-package! yasnippet-capf :when (modulep! :editor snippets) :defer t :init - (after! yasnippet - (add-hook! yas-minor-mode - (add-to-list 'completion-at-point-functions #'yasnippet-capf)))) + (add-hook! yas-minor-mode + (add-hook 'completion-at-point-functions #'yasnippet-capf 30 t))) (use-package! corfu-terminal :when (not (display-graphic-p)) diff --git a/modules/completion/corfu/packages.el b/modules/completion/corfu/packages.el index 1d9f48f6c..b53626aab 100644 --- a/modules/completion/corfu/packages.el +++ b/modules/completion/corfu/packages.el @@ -2,7 +2,7 @@ ;;; completion/corfu/packages.el (package! corfu :recipe (:files ("*.el" "extensions/*.el")) :pin "b2b9a2312f58117514724e729fda43efc4433ecd") -(package! cape :pin "116063b9ee912cbaa7318dbe6597ade4a62b3f59") +(package! cape :pin "bee13e568d42ffec9010fbf795e8f942973da174") (when (modulep! +icons) (package! nerd-icons-completion :pin "c2db8557a3c1a9588d111f8c8e91cae96ee85010") (package! nerd-icons-corfu :pin "5082a22dfbdea092fcc475db3484cb3ff812b730")) From 241b8896da7a0edd46cb80bc940c4035b884498c Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Fri, 27 Oct 2023 16:00:03 -0300 Subject: [PATCH 11/17] fix(corfu): improve keybinding config --- modules/completion/corfu/README.org | 55 +++++++------- modules/completion/corfu/config.el | 109 ++++++++++++---------------- 2 files changed, 76 insertions(+), 88 deletions(-) diff --git a/modules/completion/corfu/README.org b/modules/completion/corfu/README.org index e74332d16..a72f336bc 100644 --- a/modules/completion/corfu/README.org +++ b/modules/completion/corfu/README.org @@ -64,27 +64,28 @@ 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 is visible, the following relevant keys are available: -| Keybind | Description | -|----------+---------------------------------------------------------| -| [[kbd:][]] | Go to next candidate | -| [[kbd:][]] | Go to previous candidate | -| [[kbd:][C-n]] | Go to next candidate | -| [[kbd:][C-p]] | Go to previous candidate | -| [[kbd:][C-j]] | (evil) Go to next candidate | -| [[kbd:][C-k]] | (evil) Go to previous candidate | -| [[kbd:][C-]] | Go to next doc line | -| [[kbd:][C-]] | Go to previous doc line | -| [[kbd:][C-S-n]] | Go to next doc line | -| [[kbd:][C-S-p]] | Go to previous doc line | -| [[kbd:][C-S-j]] | (evil) Go to next doc line | -| [[kbd:][C-S-k]] | (evil) Go to previous doc line | -| [[kbd:][C-h]] | Toggle documentation (if available) | +| Keybind | Description | +|----------+------------------------------------------------------------------| +| [[kbd:][]] | Go to next candidate | +| [[kbd:][]] | Go to previous candidate | +| [[kbd:][C-n]] | Go to next candidate | +| [[kbd:][C-p]] | Go to previous candidate | +| [[kbd:][C-j]] | (evil) Go to next candidate | +| [[kbd:][C-k]] | (evil) Go to previous candidate | +| [[kbd:][C-]] | Go to next doc line | +| [[kbd:][C-]] | Go to previous doc line | +| [[kbd:][C-S-n]] | Go to next doc line | +| [[kbd:][C-S-p]] | Go to previous doc line | +| [[kbd:][C-S-j]] | (evil) Go to next doc line | +| [[kbd:][C-S-k]] | (evil) Go to previous doc line | +| [[kbd:][C-h]] | Toggle documentation (if available) | | [[kbd:][M-m]] | 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:][SPC]] | Quit autocompletion after a wildcard or pass-through | -| [[kbd:][C-SPC]] | (when completing) Insert separator (see below) | +| [[kbd:][M-S-j]] | (evil) Export to minibuffer (if [[doom-module::completion vertico]]) | +| [[kbd:][RET]] | Insert candidate | +| [[kbd:][SPC]] | (after wildcard) Reset completion | +| [[kbd:][DEL]] | Reset completion | | [[kbd:][C-SPC]] | Complete (unless [[doom-module::completion corfu +tng]]) | +| [[kbd:][C-SPC]] | (when completing) Insert separator (see below) | If you prefer a [[kbd:][TAB]]-centric completion style, enable the [[doom-module::completion corfu +tng]] flag so that, instead, you trigger completion with [[kbd:][TAB]], getting the following @@ -95,16 +96,16 @@ additional binds: | [[kbd:][TAB]] | Complete | | [[kbd:][TAB]] | (when completing) Go to next candidate | | [[kbd:][S-TAB]] | (when completing) Go to previous candidate | -| [[kbd:][DEL]] | (when completing) Reset completion DWIM-style | ** Searching with multiple keywords -If the [[doom-module::completion corfu +orderless]] flag is enabled, users can perform code -completion with multiple search keywords by use of space as the separator. More -information can be found [[https://github.com/oantolin/orderless#company][here]]. Pressing [[kdb:][C-SPC]] again while completing inserts a -space as separator. This allows searching with space-separated terms; each piece -will match individually and in any order, with smart casing. Pressing just [[kbd:][SPC]] -acts as normal and restarts completion, so that when typing sentences it doesn't -try to complete the whole sentence instead of just the word. +If the [[doom-module::completion corfu +orderless]] flag is enabled, users can +perform code completion with multiple search keywords by use of space or ~,~ as +the separator. More information can be found [[https://github.com/oantolin/orderless#company][here]]. Pressing [[kdb:][C-SPC]] again while +completing inserts a space as separator. This allows searching with +space-separated terms; each piece will match individually and in any order, with +smart casing. Pressing just [[kbd:][SPC]] acts as normal and quits completion, so that +when typing sentences it doesn't try to complete the whole sentence instead of +just the word. Furthermore, if you also have [[var:+orderless-wildcard-character]] set (by default it's the comma key), then that character acts as a wildcard when typed diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index d558f8e9e..3a8315204 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -83,15 +83,6 @@ This variable needs to be set at the top-level before any `after!' blocks.") (apply (timer--function evil--ex-search-update-timer) (timer--args evil--ex-search-update-timer))))) - ;; Do not make us type RET twice with Corfu. - (defun corfu--maybe-return-filter (cmd) - (if (eq corfu--index -1) (corfu-quit) cmd)) - (keymap-set corfu-map "RET" `(menu-item "corfu-maybe-return" corfu-insert - :filter corfu--maybe-return-filter)) - (keymap-set - corfu-map "" `(menu-item "corfu-maybe-return" corfu-insert - :filter corfu--maybe-return-filter)) - ;; Allow completion after `:' in Lispy. (add-to-list 'corfu-auto-commands #'lispy-colon) @@ -133,18 +124,16 @@ This variable needs to be set at the top-level before any `after!' blocks.") (setq orderless-component-separator (+orderless-escapable-split-fn +orderless-wildcard-character)) (setq corfu-separator +orderless-wildcard-character) - (keymap-set corfu-map (char-to-string +orderless-wildcard-character) - #'+corfu-insert-wildcard-separator) - ;; Quit completion after typing the wildcard followed by a space. - (keymap-set corfu-map "SPC" - `(menu-item "corfu-maybe-quit" nil - :filter - ,(lambda (_) - (when (and (> (point) (point-min)) - (eq (char-before) - +orderless-wildcard-character)) - (corfu-quit) - nil)))))) + (defun +corfu--maybe-quit-spc-filter (cmd) + (when (and (> (point) (point-min)) + (eq (char-before) +orderless-wildcard-character)) + cmd)) + (let ((wildstr (char-to-string +orderless-wildcard-character)) + (mi-spc '(menu-item "corfu-maybe-quit" corfu-reset :filter +corfu--maybe-quit-spc-filter))) + (map! :map corfu-map + wildstr #'+corfu-insert-wildcard-separator + ;; Quit completion after typing the wildcard followed by a space. + "SPC" mi-spc)))) (add-hook! 'evil-insert-state-exit-hook (defun +corfu-quit-on-evil-insert-state-exit-h () @@ -157,36 +146,34 @@ This variable needs to be set at the top-level before any `after!' blocks.") (when (modulep! +icons) (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) - ;; Reset completion DWIM-style with backspace. - (when (modulep! +tng) - (defun corfu--maybe-reset-backspace-filter (cmd) - (when (and (> corfu--index -1) - (eq corfu-preview-current 'insert)) - cmd)) - (keymap-set corfu-map "DEL" `(menu-item "corfu-maybe-reset" corfu-reset - :filter corfu--maybe-reset-backspace-filter)) - (keymap-set - corfu-map "" `(menu-item "corfu-maybe-reset" corfu-reset - :filter corfu--maybe-reset-backspace-filter))) - - (map! (:map 'corfu-map - (:when (modulep! +orderless) - :gi "C-SPC" #'corfu-insert-separator) - (:when (modulep! +tng) - [tab] #'corfu-next - [backtab] #'corfu-previous - "TAB" #'corfu-next - "S-TAB" #'corfu-previous))) - (after! evil-collection-corfu - (evil-collection-define-key 'insert 'corfu-map - (kbd "RET") #'corfu-insert - [return] #'corfu-insert)) + (defun +corfu--maybe-reset-backspace-filter (cmd) + (when (and (modulep! +tng) + (> corfu--index -1) + (eq corfu-preview-current 'insert)) + cmd)) + (defun +corfu--maybe-quit-return-filter (cmd) + (let ((corfu--index (if (> corfu--index -1) corfu--index 0))) + (corfu-insert)) + cmd) + (let ((mi-del '(menu-item "corfu-maybe-reset-backspace-filter" corfu-reset + :filter +corfu--maybe-reset-backspace-filter))) + (map! :map corfu-map + [return] #'corfu-insert + "RET" #'corfu-insert + (:when (modulep! +orderless) + :gi "C-SPC" #'corfu-insert-separator) + (:when (modulep! +tng) + [tab] #'corfu-next + [backtab] #'corfu-previous + "TAB" #'corfu-next + "S-TAB" #'corfu-previous + [backspace] mi-del + "DEL" mi-del))) (after! vertico - (map! :map 'corfu-map "M-m" #'corfu-move-to-minibuffer) - (after! evil-collection-corfu - (evil-collection-define-key 'insert 'corfu-map - (kbd "M-j") #'corfu-move-to-minibuffer)))) + (map! :map corfu-map + "M-m" #'corfu-move-to-minibuffer + (:when (modulep! :editor evil) "M-J" #'corfu-move-to-minibuffer)))) (use-package! cape :defer t @@ -281,15 +268,15 @@ This variable needs to be set at the top-level before any `after!' blocks.") :hook (corfu-mode . corfu-popupinfo-mode) :config (setq corfu-popupinfo-delay '(0.5 . 1.0)) - (map! (:map 'corfu-map - "C-" #'corfu-popupinfo-scroll-down - "C-" #'corfu-popupinfo-scroll-up - "C-S-p" #'corfu-popupinfo-scroll-down - "C-S-n" #'corfu-popupinfo-scroll-up - "C-h" #'corfu-popupinfo-toggle) - (:map 'corfu-popupinfo-map - :when (modulep! :editor evil) - ;; Reversed because popupinfo assumes opposite of what feels intuitive - ;; with evil. - "C-S-k" #'corfu-popupinfo-scroll-down - "C-S-j" #'corfu-popupinfo-scroll-up))) + (map! :map corfu-map + "C-" #'corfu-popupinfo-scroll-down + "C-" #'corfu-popupinfo-scroll-up + "C-S-p" #'corfu-popupinfo-scroll-down + "C-S-n" #'corfu-popupinfo-scroll-up + "C-h" #'corfu-popupinfo-toggle) + (map! :when (modulep! :editor evil) + :map corfu-popupinfo-map + ;; Reversed because popupinfo assumes opposite of what feels intuitive + ;; with evil. + "C-S-k" #'corfu-popupinfo-scroll-down + "C-S-j" #'corfu-popupinfo-scroll-up)) From 7a4d8572f7dfd1a1ac0f387df988534be68d8861 Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Fri, 27 Oct 2023 16:09:14 -0300 Subject: [PATCH 12/17] tweak(corfu): place extra CAPFs behind flags --- modules/completion/corfu/README.org | 14 +++++-- modules/completion/corfu/config.el | 65 ++++++++++++++++------------- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/modules/completion/corfu/README.org b/modules/completion/corfu/README.org index a72f336bc..224d6959c 100644 --- a/modules/completion/corfu/README.org +++ b/modules/completion/corfu/README.org @@ -20,12 +20,20 @@ highly non-native, but has some extra features and more maturity. - +icons :: Display icons beside completion suggestions. - +tng :: - Invoke completion on [[kbd:][TAB]]. When corfu is active, [[kbd:][TAB]] and [[kbd:][S-TAB]] will navigate - the completion candidates. Arrow keys and evil-style movement are still - supported. + Invoke completion on [[kbd:][TAB]]. When corfu is active, [[kbd:][TAB]] and + [[kbd:][S-TAB]] will navigate the completion candidates. Arrow keys and + evil-style movement are still supported. - +orderless :: Pull in [[doom-package:orderless]] if necessary and apply multi-component completion (still needed if [[doom-module::completion vertico]] is active). +- +dabbrev :: + Enable and configure [[doom-package:dabbrev]] as a nigh on everywhere 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 - [[doom-package:corfu]] diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index 3a8315204..90ce1a9b0 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -178,35 +178,39 @@ This variable needs to be set at the top-level before any `after!' blocks.") (use-package! cape :defer t :init - ;; Set up `cape-dabbrev' and `cape-line' options. - (defun +cape-line-buffers () - (cl-loop for buf in (buffer-list) - if (or (eq major-mode (buffer-local-value 'major-mode buf)) - (< (buffer-size buf) +cape-buffer-scanning-size-limit)) - collect buf)) - (defun +dabbrev-friend-buffer-p (other-buffer) - (< (buffer-size other-buffer) +cape-buffer-scanning-size-limit)) - (setq cape-dabbrev-check-other-buffers t - cape-line-buffer-function #'+cape-line-buffers - dabbrev-friend-buffer-function #'+dabbrev-friend-buffer-p - dabbrev-ignored-buffer-regexps - '("\\.\\(?:pdf\\|jpe?g\\|png\\|svg\\|eps\\)\\'" - "^ " - "\\(TAGS\\|tags\\|ETAGS\\|etags\\|GTAGS\\|GRTAGS\\|GPATH\\)\\(<[0-9]+>\\)?") - dabbrev-upcase-means-case-search t) - (add-hook! prog-mode (add-hook 'completion-at-point-functions #'cape-file -10 t)) (add-hook! (org-mode markdown-mode) (add-hook 'completion-at-point-functions #'cape-elisp-block 0 t)) ;; Enable Dabbrev completion basically everywhere as a fallback. - (add-hook! (prog-mode text-mode conf-mode comint-mode minibuffer-setup - eshell-mode) - (add-hook 'completion-at-point-functions #'cape-dabbrev 20 t)) + (when (modulep! +dabbrev) + ;; Set up `cape-dabbrev' options. + (defun +dabbrev-friend-buffer-p (other-buffer) + (< (buffer-size other-buffer) +cape-buffer-scanning-size-limit)) + (setq cape-dabbrev-check-other-buffers t + dabbrev-friend-buffer-function #'+dabbrev-friend-buffer-p + dabbrev-ignored-buffer-regexps + '("\\.\\(?:pdf\\|jpe?g\\|png\\|svg\\|eps\\)\\'" + "^ " + "\\(TAGS\\|tags\\|ETAGS\\|etags\\|GTAGS\\|GRTAGS\\|GPATH\\)\\(<[0-9]+>\\)?") + dabbrev-upcase-means-case-search t) + (add-hook! (prog-mode text-mode conf-mode comint-mode minibuffer-setup + eshell-mode) + (add-hook 'completion-at-point-functions #'cape-dabbrev 20 t))) + (when (modulep! +line) + ;; Set up `cape-line' options. + (defun +cape-line-buffers () + (cl-loop for buf in (buffer-list) + if (or (eq major-mode (buffer-local-value 'major-mode buf)) + (< (buffer-size buf) +cape-buffer-scanning-size-limit)) + collect buf)) + (setq cape-line-buffer-function #'+cape-line-buffers) + (add-hook! (text-mode comint-mode minibuffer-setup) + (add-hook 'completion-at-point-functions #'cape-line 20 t))) ;; Complete emojis :). - (when (> emacs-major-version 28) + (when (and (modulep! +emoji) (> emacs-major-version 28)) (add-hook! (prog-mode conf-mode) (add-hook 'completion-at-point-functions (cape-capf-inside-faces @@ -220,15 +224,16 @@ This variable needs to be set at the top-level before any `after!' blocks.") (cape-capf-prefix-length #'cape-emoji 1) 10 t))) ;; Enable dictionary-based autocompletion. - (add-hook! text-mode - (add-hook 'completion-at-point-functions #'cape-dict 40 t)) - (add-hook! (prog-mode conf-mode) - (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)) + (when (modulep! +dict) + (add-hook! text-mode + (add-hook 'completion-at-point-functions #'cape-dict 40 t)) + (add-hook! (prog-mode conf-mode) + (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))) ;; Make these capfs composable. (advice-add #'comint-completion-at-point :around #'cape-wrap-nonexclusive) From 3d41c07370c5e0646ca18686a1a4f9f3b17ec228 Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Fri, 27 Oct 2023 16:21:58 -0300 Subject: [PATCH 13/17] tweak(corfu): expand autoload command triggers --- modules/completion/corfu/config.el | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index 90ce1a9b0..c5dbc2300 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -177,6 +177,50 @@ This variable needs to be set at the top-level before any `after!' blocks.") (use-package! cape :defer t + :commands + cape-abbrev + cape-dabbrev + cape-dict + cape-elisp-block + cape-elisp-symbol + cape-emoji + cape-file + cape-history + cape-keyword + cape-line + cape-rfc1345 + cape-sgml + cape-tex + cape-company-to-capf + cape-capf-super + cape-capf-buster + cape-capf-accept-all + cape-capf-debug + cape-capf-silent + cape-capf-purify + cape-capf-nonexclusive + cape-capf-noninterruptable + cape-capf-properties + cape-capf-predicate + cape-capf-prefix-length + cape-capf-inside-comment + cape-capf-inside-string + cape-capf-inside-faces + cape-capf-interactive + cape-wrap-buster + cape-wrap-accept-all + cape-wrap-debug + cape-wrap-silent + cape-wrap-purify + cape-wrap-nonexclusive + cape-wrap-noninterruptable + cape-wrap-properties + cape-wrap-predicate + cape-wrap-prefix-length + cape-wrap-inside-comment + cape-wrap-inside-string + cape-wrap-inside-faces + cape-interactive :init (add-hook! prog-mode (add-hook 'completion-at-point-functions #'cape-file -10 t)) From fc15f169dac8187e51a34879de09dcb8891e2b02 Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Sun, 29 Oct 2023 14:31:13 -0300 Subject: [PATCH 14/17] feat(corfu, vertico): use equal orderless config This removes the old `&` separator for Vertico (does anyone use that instead of just space?) in favor of escapable space and unifies orderless config with Corfu. Also implements smart separator insert/escape/reset on `C-SPC` --- modules/completion/corfu/config.el | 90 ++++++++-------------------- modules/completion/vertico/config.el | 3 +- 2 files changed, 27 insertions(+), 66 deletions(-) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index c5dbc2300..73013c51c 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -6,13 +6,6 @@ As an exception, `cape-line' will also scan buffers with the same major mode regardless of size.") -(defvar +orderless-wildcard-character ?, - "A character used as a wildcard in Corfu for fuzzy autocompletion. If you -want to match the wildcard literally in completion, you can -escape it with forward slash. Do NOT set this to SPC. - -This variable needs to be set at the top-level before any `after!' blocks.") - ;; ;;; Packages (use-package! corfu @@ -24,6 +17,7 @@ This variable needs to be set at the top-level before any `after!' blocks.") (setq corfu-auto t corfu-auto-delay 0.1 corfu-auto-prefix 2 + corfu-separator ?\s corfu-excluded-modes '(erc-mode circe-mode help-mode @@ -39,7 +33,7 @@ This variable needs to be set at the top-level before any `after!' blocks.") corfu-max-width 120 corfu-preview-current 'insert corfu-on-exact-match nil - corfu-quit-at-boundary (if (modulep! +orderless) 'separator t) + corfu-quit-at-boundary t corfu-quit-no-match (if (modulep! +orderless) 'separator t) ;; In the case of +tng, TAB should be smart regarding completion; ;; However, it should otherwise behave like normal, whatever normal was. @@ -56,7 +50,7 @@ This variable needs to be set at the top-level before any `after!' blocks.") (unless (corfu-disable-in-minibuffer-p) (setq-local corfu-echo-delay nil ;; Disable automatic echo and popup corfu-popupinfo-delay nil) - (corfu-mode 1))) + (corfu-mode +1))) (add-hook 'minibuffer-setup-hook #'corfu-enable-in-minibuffer) @@ -86,54 +80,9 @@ This variable needs to be set at the top-level before any `after!' blocks.") ;; Allow completion after `:' in Lispy. (add-to-list 'corfu-auto-commands #'lispy-colon) - (when (and (modulep! +orderless) - +orderless-wildcard-character) - (defmacro +orderless-escapable-split-fn (char) - (let ((char-string (string (if (symbolp char) (symbol-value char) char)))) - `(defun +orderless-escapable-split-on-space-or-char (s) - (mapcar - (lambda (piece) - (replace-regexp-in-string - (string 1) ,char-string - (replace-regexp-in-string - (concat (string 0) "\\|" (string 1)) - (lambda (x) - (pcase x - ("\0" " ") - ("\1" ,char-string) - (_ x))) - piece - ;; These are arguments to `replace-regexp-in-string'. - 'fixedcase 'literal) - 'fixedcase 'literal)) - (split-string (replace-regexp-in-string - (concat "\\\\\\\\\\|\\\\ \\|\\\\" - ,char-string) - (lambda (x) - (pcase x - ("\\ " "\0") - (,(concat "\\" char-string) - "\1") - (_ x))) - s 'fixedcase 'literal) - ,(concat "[ " char-string "]+") - t))))) + (when (modulep! +orderless) (after! orderless - ;; Orderless splits the string into components and then determines the - ;; matching style for each component. This is all regexp stuff. - (setq orderless-component-separator - (+orderless-escapable-split-fn +orderless-wildcard-character)) - (setq corfu-separator +orderless-wildcard-character) - (defun +corfu--maybe-quit-spc-filter (cmd) - (when (and (> (point) (point-min)) - (eq (char-before) +orderless-wildcard-character)) - cmd)) - (let ((wildstr (char-to-string +orderless-wildcard-character)) - (mi-spc '(menu-item "corfu-maybe-quit" corfu-reset :filter +corfu--maybe-quit-spc-filter))) - (map! :map corfu-map - wildstr #'+corfu-insert-wildcard-separator - ;; Quit completion after typing the wildcard followed by a space. - "SPC" mi-spc)))) + (setq orderless-component-separator #'orderless-escapable-split-on-space))) (add-hook! 'evil-insert-state-exit-hook (defun +corfu-quit-on-evil-insert-state-exit-h () @@ -146,22 +95,34 @@ This variable needs to be set at the top-level before any `after!' blocks.") (when (modulep! +icons) (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) - (defun +corfu--maybe-reset-backspace-filter (cmd) + (defun +corfu--reset-or-passthrough (cmd) (when (and (modulep! +tng) (> corfu--index -1) (eq corfu-preview-current 'insert)) cmd)) - (defun +corfu--maybe-quit-return-filter (cmd) - (let ((corfu--index (if (> corfu--index -1) corfu--index 0))) - (corfu-insert)) - cmd) - (let ((mi-del '(menu-item "corfu-maybe-reset-backspace-filter" corfu-reset - :filter +corfu--maybe-reset-backspace-filter))) + (defun +corfu--backward-toggle-escape-sep (cmd) + (save-excursion + (backward-char 1) + (if (looking-back "\\\\" -1) + #'corfu-reset + (lambda () + (interactive) + (save-excursion + (backward-char 1) + (insert-char ?\\)))))) + (defun +corfu--insert-separator-or-toggle-escape (cmd) + (if (char-equal (char-before) corfu-separator) + (+corfu--backward-toggle-escape-sep cmd) + cmd)) + (let ((mi-del '(menu-item "corfu-reset-or-passthrough" corfu-reset + :filter +corfu--maybe-reset-backspace-filter)) + (mi-c-spc '(menu-item "corfu-insert-separator-or-toggle-escape" corfu-insert-separator + :filter +corfu--insert-separator-or-toggle-escape))) (map! :map corfu-map [return] #'corfu-insert "RET" #'corfu-insert (:when (modulep! +orderless) - :gi "C-SPC" #'corfu-insert-separator) + :gi "C-SPC" mi-c-spc) (:when (modulep! +tng) [tab] #'corfu-next [backtab] #'corfu-previous @@ -176,7 +137,6 @@ This variable needs to be set at the top-level before any `after!' blocks.") (:when (modulep! :editor evil) "M-J" #'corfu-move-to-minibuffer)))) (use-package! cape - :defer t :commands cape-abbrev cape-dabbrev diff --git a/modules/completion/vertico/config.el b/modules/completion/vertico/config.el index a4efa7c4e..ac4bbad05 100644 --- a/modules/completion/vertico/config.el +++ b/modules/completion/vertico/config.el @@ -98,6 +98,7 @@ orderless." ;; Flex matching ((string-prefix-p "~" pattern) `(orderless-flex . ,(substring pattern 1))) ((string-suffix-p "~" pattern) `(orderless-flex . ,(substring pattern 0 -1))))) + ;; TODO: Find a way to deduplicate this code from the corfu module. (add-to-list 'completion-styles-alist '(+vertico-basic-remote @@ -110,7 +111,7 @@ orderless." ;; find-file etc. completion-category-overrides '((file (styles +vertico-basic-remote orderless partial-completion))) orderless-style-dispatchers '(+vertico-orderless-dispatch) - orderless-component-separator "[ &]") + orderless-component-separator #'orderless-escapable-split-on-space) ;; ...otherwise find-file gets different highlighting than other commands (set-face-attribute 'completions-first-difference nil :inherit nil)) From a16e544c7ac158ed9938ea74e7ee6a11bb70f6ce Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Tue, 31 Oct 2023 21:54:50 -0300 Subject: [PATCH 15/17] bump: :completion corfu --- modules/completion/corfu/packages.el | 10 +++++----- modules/completion/vertico/packages.el | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/completion/corfu/packages.el b/modules/completion/corfu/packages.el index b53626aab..0107b7278 100644 --- a/modules/completion/corfu/packages.el +++ b/modules/completion/corfu/packages.el @@ -1,14 +1,14 @@ ;; -*- no-byte-compile: t; -*- ;;; completion/corfu/packages.el -(package! corfu :recipe (:files ("*.el" "extensions/*.el")) :pin "b2b9a2312f58117514724e729fda43efc4433ecd") -(package! cape :pin "bee13e568d42ffec9010fbf795e8f942973da174") +(package! corfu :recipe (:files ("*.el" "extensions/*.el")) :pin "457042d486e7542b9a6a832e47e6833d217ffd47") +(package! cape :pin "abacb231157e0c90e29bdda6d15b4b448e48ffbd") (when (modulep! +icons) (package! nerd-icons-completion :pin "c2db8557a3c1a9588d111f8c8e91cae96ee85010") - (package! nerd-icons-corfu :pin "5082a22dfbdea092fcc475db3484cb3ff812b730")) + (package! nerd-icons-corfu :pin "7077bb76fefc15aed967476406a19dc5c2500b3c")) (when (modulep! +orderless) - (package! orderless :pin "d6b402a89e234d0e6166247ed6025f9acc8b4d9a")) + (package! orderless :pin "89eb3775daa53cfb52ad03015410c23f28c72d30")) (when (modulep! :os tty) (package! corfu-terminal :pin "501548c3d51f926c687e8cd838c5865ec45d03cc")) (when (modulep! :editor snippets) - (package! yasnippet-capf :pin "40654214db7a44db3a99321447632b43a10fae57")) + (package! yasnippet-capf :pin "a0a6b1c2bb6decdad5cf9b74202f0042f494a6ab")) diff --git a/modules/completion/vertico/packages.el b/modules/completion/vertico/packages.el index 68f1b73e9..947c8b7a5 100644 --- a/modules/completion/vertico/packages.el +++ b/modules/completion/vertico/packages.el @@ -6,7 +6,7 @@ :files ("*.el" "extensions/*.el")) :pin "a28370d07f35c5387c7a9ec2e5b67f0d4598058d") -(package! orderless :pin "e6784026717a8a6a7dcd0bf31fd3414f148c542e") +(package! orderless :pin "89eb3775daa53cfb52ad03015410c23f28c72d30") (package! consult :pin "fe49dedd71802ff97be7b89f1ec4bd61b98c2b13") (package! consult-dir :pin "ed8f0874d26f10f5c5b181ab9f2cf4107df8a0eb") From 46ce67aa6dc6ae7fe2f615134d943c1fdbe28138 Mon Sep 17 00:00:00 2001 From: StrawberryTea Date: Mon, 6 Nov 2023 14:48:33 -0600 Subject: [PATCH 16/17] fix(corfu): move orderless config earlier --- modules/completion/corfu/config.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index 73013c51c..afdfa65ea 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -12,6 +12,10 @@ major mode regardless of size.") :hook (doom-first-buffer . global-corfu-mode) :hook (org-mode . corfu-mode) :init + (when (modulep! +orderless) + (after! orderless + (setq orderless-component-separator #'orderless-escapable-split-on-space))) + ;; Auto-completion settings, must be set before calling `global-corfu-mode'. ;; Due to lazy-loading, overriding these in config.el works too. (setq corfu-auto t @@ -80,10 +84,6 @@ major mode regardless of size.") ;; Allow completion after `:' in Lispy. (add-to-list 'corfu-auto-commands #'lispy-colon) - (when (modulep! +orderless) - (after! orderless - (setq orderless-component-separator #'orderless-escapable-split-on-space))) - (add-hook! 'evil-insert-state-exit-hook (defun +corfu-quit-on-evil-insert-state-exit-h () ;; This predicate a workaround for unexpected calls to `corfu-quit' in From f2562bbb4ab6e3aaa777f89fa989a8d3dbb970f1 Mon Sep 17 00:00:00 2001 From: StrawberryTea Date: Mon, 6 Nov 2023 14:50:07 -0600 Subject: [PATCH 17/17] feat(corfu): always configure dabbrev & line --- modules/completion/corfu/config.el | 36 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index afdfa65ea..a6014cbf2 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -188,28 +188,30 @@ major mode regardless of size.") (add-hook 'completion-at-point-functions #'cape-elisp-block 0 t)) ;; Enable Dabbrev completion basically everywhere as a fallback. + ;; Set up `cape-dabbrev' options. + (defun +dabbrev-friend-buffer-p (other-buffer) + (< (buffer-size other-buffer) +cape-buffer-scanning-size-limit)) + (setq cape-dabbrev-check-other-buffers t + dabbrev-friend-buffer-function #'+dabbrev-friend-buffer-p + dabbrev-ignored-buffer-regexps + '("\\.\\(?:pdf\\|jpe?g\\|png\\|svg\\|eps\\)\\'" + "^ " + "\\(TAGS\\|tags\\|ETAGS\\|etags\\|GTAGS\\|GRTAGS\\|GPATH\\)\\(<[0-9]+>\\)?") + dabbrev-upcase-means-case-search t) (when (modulep! +dabbrev) - ;; Set up `cape-dabbrev' options. - (defun +dabbrev-friend-buffer-p (other-buffer) - (< (buffer-size other-buffer) +cape-buffer-scanning-size-limit)) - (setq cape-dabbrev-check-other-buffers t - dabbrev-friend-buffer-function #'+dabbrev-friend-buffer-p - dabbrev-ignored-buffer-regexps - '("\\.\\(?:pdf\\|jpe?g\\|png\\|svg\\|eps\\)\\'" - "^ " - "\\(TAGS\\|tags\\|ETAGS\\|etags\\|GTAGS\\|GRTAGS\\|GPATH\\)\\(<[0-9]+>\\)?") - dabbrev-upcase-means-case-search t) (add-hook! (prog-mode text-mode conf-mode comint-mode minibuffer-setup eshell-mode) (add-hook 'completion-at-point-functions #'cape-dabbrev 20 t))) + + + ;; Set up `cape-line' options. + (defun +cape-line-buffers () + (cl-loop for buf in (buffer-list) + if (or (eq major-mode (buffer-local-value 'major-mode buf)) + (< (buffer-size buf) +cape-buffer-scanning-size-limit)) + collect buf)) + (setq cape-line-buffer-function #'+cape-line-buffers) (when (modulep! +line) - ;; Set up `cape-line' options. - (defun +cape-line-buffers () - (cl-loop for buf in (buffer-list) - if (or (eq major-mode (buffer-local-value 'major-mode buf)) - (< (buffer-size buf) +cape-buffer-scanning-size-limit)) - collect buf)) - (setq cape-line-buffer-function #'+cape-line-buffers) (add-hook! (text-mode comint-mode minibuffer-setup) (add-hook 'completion-at-point-functions #'cape-line 20 t)))