dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

commit 0d3c907c6ff8002d31ee757798e26f515e39fbfe
parent b3df86b7aba0c64ad86878bf0f36d99eb9df2cf5
Author: Lukas Henkel <lh@entf.net>
Date:   Sat,  6 Apr 2024 20:35:49 +0200

Upgrade corfu

Diffstat:
Delpa/corfu-1.0.signed | 3---
Delpa/corfu-1.0/CHANGELOG.org | 81-------------------------------------------------------------------------------
Delpa/corfu-1.0/README-elpa | 772-------------------------------------------------------------------------------
Delpa/corfu-1.0/README.org | 616-------------------------------------------------------------------------------
Delpa/corfu-1.0/corfu-echo.el | 108-------------------------------------------------------------------------------
Delpa/corfu-1.0/corfu-history.el | 92-------------------------------------------------------------------------------
Delpa/corfu-1.0/corfu-indexed.el | 97-------------------------------------------------------------------------------
Delpa/corfu-1.0/corfu-info.el | 116-------------------------------------------------------------------------------
Delpa/corfu-1.0/corfu-pkg.el | 2--
Delpa/corfu-1.0/corfu-popupinfo.el | 522-------------------------------------------------------------------------------
Delpa/corfu-1.0/corfu-quick.el | 154-------------------------------------------------------------------------------
Delpa/corfu-1.0/corfu.el | 1323-------------------------------------------------------------------------------
Delpa/corfu-1.0/corfu.info | 758-------------------------------------------------------------------------------
Aelpa/corfu-1.3.signed | 3+++
Aelpa/corfu-1.3/CHANGELOG.org | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/README-elpa | 804+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/README.org | 644+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Relpa/corfu-1.0/corfu-autoloads.el -> elpa/corfu-1.3/corfu-autoloads.el | 0
Aelpa/corfu-1.3/corfu-echo.el | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/corfu-history.el | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/corfu-indexed.el | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/corfu-info.el | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/corfu-pkg.el | 2++
Aelpa/corfu-1.3/corfu-popupinfo.el | 523+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/corfu-quick.el | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/corfu.el | 1398+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aelpa/corfu-1.3/corfu.info | 795+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Relpa/corfu-1.0/dir -> elpa/corfu-1.3/dir | 0
28 files changed, 4851 insertions(+), 4644 deletions(-)

diff --git a/elpa/corfu-1.0.signed b/elpa/corfu-1.0.signed @@ -1,2 +0,0 @@ -Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2023-12-01T11:05:05+0100 using RSA -Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) <elpasign@elpa.gnu.org> (trust undefined) created at 2023-12-01T11:05:05+0100 using EDDSA -\ No newline at end of file diff --git a/elpa/corfu-1.0/CHANGELOG.org b/elpa/corfu-1.0/CHANGELOG.org @@ -1,81 +0,0 @@ -#+title: corfu.el - Changelog -#+author: Daniel Mendler -#+language: en - -* Version 1.0 (2023-12-01) - -- Bug fixes. -- =corfu-quick=: Use a slightly different scheme to support more candidates. -- =corfu-reset=: Quit immediately if input did not change. - -* Version 0.38 (2023-08-14) - -- =corfu-quick=: Bugfix. -- =corfu-mode-map=: Add mode map. -- Replace =corfu-excluded-modes= with =global-corfu-modes=, the Emacs 28 convention - for globalized minor modes. - -* Version 0.37 (2023-07-02) - -- Bugfixes. -- Improve child frame display code, =corfu--popup-show= takes a =posn= argument. -- Ensure that the popup font matches the font of the parent frame. -- Close popup when window selection changes. -- Remove =corfu-history-length=. Instead set the =history-length= property of - =corfu-history= variable. -- =corfu-info-documentation=, =corfu-info-location=: Make buffer and window - persistent if called with prefix argument. - -* Version 0.36 (2023-03-27) - -- Drop obsolete =corfu-preselect-first=. -- =corfu-popupinfo-delay= and =corfu-echo-delay=: Remove support for value =t=. - Instant updates are not recommended. It is still possible to use a small value - for the delay. -- Rename =corfu-excluded-modes= to =corfu-exclude-modes= (Naming convention). -- Remove call to =undo-boundary=, which caused issues with auto completion. - -* Version 0.35 (2023-02-17) - -- =corfu-popupinfo=: Take more text into account when computing popup width. -- =corfu-popupinfo=: Change keybindings, remap =corfu-info-documentation/location=. -- =corfu-popupinfo=: Add commands =corfu-popupinfo-beginning/end=. -- =corfu-popupinfo=: Improve popup placement. -- Add =corfu-prompt-beginning= and =corfu-prompt-end= commands. -- Add =corfu-preselect= option, deprecate =corfu-preselect-first=. -- Use =cl-defgeneric= internally as mechanism to allow extensions to override - functionality, e.g., the candidate formatting and display. - -* Version 0.34 (2022-12-03) - -- Bugfixes -- Popup frame code updated for Emacs 29. Please report any issues. -- =corfu-popupinfo-direction=: Variable must be a list of directions. -- Support height adjustments of =corfu-default= face - -* Version 0.33 (2022-11-21) - -- =corfu-popupinfo=: Bugfixes - -* Version 0.31 (2022-11-20) - -- =corfu-echo=, =corfu-quick=: Bugfixes for interaction issue. - -* Version 0.30 (2022-11-19) - -- =corfu-popupinfo=: Bugfixes and improvements. - -* Version 0.29 (2022-11-19) - -- BREAKING: Extract the =corfu-echo= extension from =corfu.el=. In order to see echo - messages, enable =corfu-echo-mode=. You probably want to enable either - =corfu-echo-mode= or =corfu-popupinfo-mode=. -- BREAKING: Rename =corfu-echo-documentation= to =corfu-echo-delay=. -- Add =corfu-popupinfo= extension to display candidate documentation and location - in a small child frame next to the candidate menu. This extension has been - contributed by Yuwei Tian who assigned copyright to the FSF. The extension - supersedes Yuwei's =corfu-doc= package. - -* Version 0.28 (2022-10-16) - -- Start of changelog. diff --git a/elpa/corfu-1.0/README-elpa b/elpa/corfu-1.0/README-elpa @@ -1,772 +0,0 @@ - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - CORFU.EL - COMPLETION IN REGION FUNCTION - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - -Corfu enhances in-buffer completion with a small completion popup. The -current candidates are shown in a popup below or above the point. The -candidates can be selected by moving up and down. Corfu is the -minimalistic in-buffer completion counterpart of the [Vertico] -minibuffer UI. - -Corfu is a small package, which relies on the Emacs completion -facilities and concentrates on providing a polished completion -UI. In-buffer completion UIs in Emacs can hook into -`completion-in-region', which implements the interaction with the -user. Completions at point are either provided by commands like -`dabbrev-completion' or by pluggable backends -(`completion-at-point-functions', Capfs) and are then passed to -`completion-in-region'. Many programming, text and shell major modes -implement a Capf. Corfu does not include its own completion -backends. The Emacs built-in Capfs and the Capfs provided by third-party -programming language packages are often sufficient. Additional Capfs and -completion utilities are provided by the [Cape] package. - -*NOTE*: Corfu uses child frames to show the popup and falls back to the -default setting of the `completion-in-region-function' on non-graphical -displays. If you want to use Corfu in the terminal, install the package -[corfu-terminal], which provides an alternative overlay-based display. - -Table of Contents -───────────────── - -1. Features -2. Installation and Configuration -.. 1. Auto completion -.. 2. Completing in the minibuffer -.. 3. Completing in the Eshell or Shell -.. 4. Orderless completion -.. 5. TAB-only completion -.. 6. TAB-and-Go completion -.. 7. Transfer completion to the minibuffer -3. Key bindings -4. Extensions -5. Complementary packages -6. Alternatives -7. Debugging Corfu -8. Contributions - - -[Vertico] <https://github.com/minad/vertico> - -[Cape] <https://github.com/minad/cape> - -[corfu-terminal] <https://codeberg.org/akib/emacs-corfu-terminal> - - -1 Features -══════════ - - • Timer-based auto-completions (/off/ by default, set `corfu-auto'). - • Popup display with scrollbar indicator and arrow key navigation. - • The popup can be summoned explicitly by pressing `TAB' at any time. - • The current candidate is inserted with `TAB' and selected with - `RET'. - • Candidate sorting by prefix, string length and alphabetically. - • The selected candidate is previewed (configurable via - `corfu-preview-current'). - • The selected candidate is automatically committed on further input - by default. (configurable via `corfu-preview-current'). - • Supports the [Orderless] completion style. The filter string can - contain arbitrary characters, after inserting a space via `M-SPC' - (configurable via `corfu-quit-at-boundary' and `corfu-separator'). - • Lazy completion candidate highlighting for performance. - • Support for candidate annotations (`annotation-function', - `affixation-function'). - • Deprecated candidates are displayed as crossed out. - • Icons can be provided by an external package via margin formatter - functions. - • Rich set of extensions: Quick keys, Index keys, Sorting by history, - Candidate documentation in echo area, popup or separate buffer. - - -[Orderless] <https://github.com/oantolin/orderless> - - -2 Installation and Configuration -════════════════════════════════ - - Corfu is available from [GNU ELPA], such that it can be installed - directly via `package-install'. After installation, the global minor - mode can be enabled with `M-x global-corfu-mode'. In order to - configure Corfu and other packages in your init.el, you may want to - use `use-package'. - - Corfu is highly flexible and customizable via `corfu-*' customization - variables, such that you can adapt it precisely to your - requirements. However in order to quickly try out the Corfu completion - package, it should be sufficient to activate `global-corfu-mode'. You - can experiment with manual completion for example in an Elisp buffer - or in an Eshell or Shell buffer. For auto completion, set `corfu-auto' - to t before turning on `global-corfu-mode'. - - Here is an example configuration: - - ┌──── - │ (use-package corfu - │ ;; Optional customizations - │ ;; :custom - │ ;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' - │ ;; (corfu-auto t) ;; Enable auto completion - │ ;; (corfu-separator ?\s) ;; Orderless field separator - │ ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary - │ ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match - │ ;; (corfu-preview-current nil) ;; Disable current candidate preview - │ ;; (corfu-preselect 'prompt) ;; Preselect the prompt - │ ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches - │ ;; (corfu-scroll-margin 5) ;; Use scroll margin - │ - │ ;; Enable Corfu only for certain modes. - │ ;; :hook ((prog-mode . corfu-mode) - │ ;; (shell-mode . corfu-mode) - │ ;; (eshell-mode . corfu-mode)) - │ - │ ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can - │ ;; be used globally (M-/). See also the customization variable - │ ;; `global-corfu-modes' to exclude certain modes. - │ :init - │ (global-corfu-mode)) - │ - │ ;; A few more useful configurations... - │ (use-package emacs - │ :init - │ ;; TAB cycle if there are only few candidates - │ (setq completion-cycle-threshold 3) - │ - │ ;; Emacs 28: Hide commands in M-x which do not apply to the current mode. - │ ;; Corfu commands are hidden, since they are not supposed to be used via M-x. - │ ;; (setq read-extended-command-predicate - │ ;; #'command-completion-default-include-p) - │ - │ ;; Enable indentation+completion using the TAB key. - │ ;; `completion-at-point' is often bound to M-TAB. - │ (setq tab-always-indent 'complete)) - └──── - - Dabbrev completion is based on `completion-in-region' and can be used - with Corfu. You may want to swap the `dabbrev-completion' with the - `dabbrev-expand' key for easier access, if you prefer completion. Also - take a look at the `cape-dabbrev' completion at point function - provided by my [Cape] package. - - ┌──── - │ ;; Use Dabbrev with Corfu! - │ (use-package dabbrev - │ ;; Swap M-/ and C-M-/ - │ :bind (("M-/" . dabbrev-completion) - │ ("C-M-/" . dabbrev-expand)) - │ ;; Other useful Dabbrev configurations. - │ :custom - │ (dabbrev-ignored-buffer-regexps '("\\.\\(?:pdf\\|jpe?g\\|png\\)\\'"))) - └──── - - If you start to configure the package more deeply, I recommend to give - the Orderless completion style a try for filtering. Orderless - completion is different from the familiar prefix TAB completion. Corfu - can be used with the default completion styles. The use of Orderless - is not a necessity. - - ┌──── - │ ;; Optionally use the `orderless' completion style. - │ (use-package orderless - │ :init - │ ;; Configure a custom style dispatcher (see the Consult wiki) - │ ;; (setq orderless-style-dispatchers '(+orderless-dispatch) - │ ;; orderless-component-separator #'orderless-escapable-split-on-space) - │ (setq completion-styles '(orderless basic) - │ completion-category-defaults nil - │ completion-category-overrides '((file (styles partial-completion))))) - └──── - - The `basic' completion style is specified as fallback in addition to - `orderless' in order to ensure that completion commands which rely on - dynamic completion tables, e.g., `completion-table-dynamic' or - `completion-table-in-turn', work correctly. See `+orderless-dispatch' - in the [Consult wiki] for an advanced Orderless style - dispatcher. Additionally enable `partial-completion' for file path - expansion. `partial-completion' is important for file wildcard - support. Multiple files can be opened at once with `find-file' if you - enter a wildcard. You may also give the `initials' completion style a - try. - - See also the [Corfu Wiki] and the [Cape manual] for additional Capf - configuration tips. For more general documentation read the chapter - about completion in the [Emacs manual]. If you want to create your own - Capfs, you can find documentation about completion in the [Elisp - manual]. - - -[GNU ELPA] <https://elpa.gnu.org/packages/corfu.html> - -[Cape] <https://github.com/minad/cape> - -[Consult wiki] <https://github.com/minad/consult/wiki> - -[Corfu Wiki] <https://github.com/minad/corfu/wiki> - -[Cape manual] <https://github.com/minad/cape> - -[Emacs manual] -<https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion.html> - -[Elisp manual] -<https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion.html> - -2.1 Auto completion -─────────────────── - - Auto completion is disabled by default, but can be enabled by setting - `corfu-auto' to t. Furthermore you may want to configure Corfu to quit - completion eagerly, such that the completion popup stays out of your - way when it appeared unexpectedly. - - ┌──── - │ ;; Enable auto completion and configure quitting - │ (setq corfu-auto t - │ corfu-quit-no-match 'separator) ;; or t - └──── - - I suggest to experiment with the various settings and key bindings to - find a configuration which works for you. There is no one perfect - configuration which fits all. Some people like auto completion, some - like manual completion, some want to cycle with TAB and some with the - arrow keys. - - In case you like auto completion settings, where the completion popup - appears immediately, better use a cheap completion style like `basic', - which performs prefix filtering. In this case Corfu completion should - still be fast in buffers with efficient completion backends. You can - try the following settings in an Elisp buffer or the Emacs scratch - buffer. Note that such settings can slow down Emacs due to the high - load on the Lisp runtime and garbage collector. - - ┌──── - │ (setq-local corfu-auto t - │ corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED - │ corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED - │ completion-styles '(basic)) - └──── - - If you want to combine fast prefix filtering and Orderless filtering - you can still do that by defining a custom Orderless completion style - via `orderless-define-completion-style'. We use a custom style - dispatcher, which enables efficient prefix filtering for input shorter - than 4 characters. Note that such a setup is advanced. Please refer to - the Orderless documentation and source code for further details. - - ┌──── - │ (defun orderless-fast-dispatch (word index total) - │ (and (= index 0) (= total 1) (length< word 4) - │ `(orderless-regexp . ,(concat "^" (regexp-quote word))))) - │ - │ (orderless-define-completion-style orderless-fast - │ (orderless-style-dispatchers '(orderless-fast-dispatch)) - │ (orderless-matching-styles '(orderless-literal orderless-regexp))) - │ - │ (setq-local corfu-auto t - │ corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED - │ corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED - │ completion-styles '(orderless-fast basic)) - └──── - - -2.2 Completing in the minibuffer -──────────────────────────────── - - Corfu can be used for completion in the minibuffer, since it relies on - child frames to display the candidates. By default, - `global-corfu-mode' does not activate `corfu-mode' in the minibuffer, - to avoid interference with specialised minibuffer completion UIs like - Vertico or Mct. However you may still want to enable Corfu completion - for commands like `M-:' (`eval-expression') or `M-!' - (`shell-command'), which read from the minibuffer. Activate - `corfu-mode' only if `completion-at-point' is bound in the - minibuffer-local keymap to achieve this effect. - - ┌──── - │ (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-auto nil) ;; Enable/disable auto completion - │ (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) - └──── - - You can also enable Corfu more generally for every minibuffer, as long - as no completion UI is active. In the following example we check for - Mct and Vertico. Furthermore we ensure that Corfu is not enabled if a - password is read from the minibuffer. - - ┌──── - │ (defun corfu-enable-always-in-minibuffer () - │ "Enable Corfu in the minibuffer if Vertico/Mct are not active." - │ (unless (or (bound-and-true-p mct--active) - │ (bound-and-true-p vertico--input) - │ (eq (current-local-map) read-passwd-map)) - │ ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion - │ (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-always-in-minibuffer 1) - └──── - - -2.3 Completing in the Eshell or Shell -───────────────────────────────────── - - When completing in the Eshell I recommend conservative local settings - without auto completion, such that the completion behavior is similar - to widely used shells like Bash, Zsh or Fish. - - ┌──── - │ (add-hook 'eshell-mode-hook - │ (lambda () - │ (setq-local corfu-auto nil) - │ (corfu-mode))) - └──── - - When pressing `RET' while the Corfu popup is visible, the - `corfu-insert' command will be invoked. This command does inserts the - currently selected candidate, but it does not send the prompt input to - Eshell or the Comint process. Therefore you often have to press `RET' - twice which feels like an unnecessary double confirmation. Fortunately - it is easy to improve this! In my configuration I define the advice - `corfu-send-shell' which sends the candidate after insertion. - - ┌──── - │ (defun corfu-send-shell (&rest _) - │ "Send completion candidate when inside comint/eshell." - │ (cond - │ ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) - │ (eshell-send-input)) - │ ((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) - │ (comint-send-input)))) - │ - │ (advice-add #'corfu-insert :after #'corfu-send-shell) - └──── - - Shell completion uses the flexible Pcomplete mechanism internally, - which allows you to program the completions per shell command. If you - want to know more, look into this [blog post], which shows how to - configure Pcomplete for git commands. - - You can try the [pcmpl-args] package which extends Pcomplete with - completion support and helpful annotation support for more - commands. Similar to the Fish shell, `pcmpl-args' uses man page - parsing and `--help' output parsing to dynamically generate - completions. Since Emacs 29, Pcomplete offers the - `pcomplete-from-help' function which parses the `--help' output of a - command and produces completions. This Emacs 29 functionality is not - completely equivalent. For example it does not display annotations in - Eshell, but this may get fixed in Emacs 30. - - Pcomplete has a few bugs on Emacs 28 and older. We can work around the - issues with the [Cape] library (Completion at point extensions). Cape - provides wrappers which sanitize the Pcomplete function. If you use - Emacs 28 or older installing these advices is recommended such that - Pcomplete works properly. On Emacs 29 the advices should not be - necessary anymore, since most of the relevant bugs have been fixed. I - therefore recommend to remove the advices on Emacs 29 and eventually - report any remaining Pcomplete issues upstream, such that they can be - fixed. - - ┌──── - │ ;; The advices are only needed on Emacs 28 and older. - │ (when (< emacs-major-version 29) - │ ;; Silence the pcomplete capf, no errors or messages! - │ (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent) - │ - │ ;; Ensure that pcomplete does not write to the buffer - │ ;; and behaves as a pure `completion-at-point-function'. - │ (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)) - └──── - - -[blog post] -<https://www.masteringemacs.org/article/pcomplete-context-sensitive-completion-emacs> - -[pcmpl-args] <https://github.com/JonWaltman/pcmpl-args.el> - -[Cape] <https://github.com/minad/cape> - - -2.4 Orderless completion -──────────────────────── - - [Orderless] is an advanced completion style that supports - multi-component search filters separated by a configurable character - (space, by default). Normally, entering characters like space which - lie outside the completion region boundaries (words, typically) causes - Corfu to quit. This behavior is helpful with auto-completion, which - may pop-up when not desired, e.g. on entering a new variable - name. Just keep typing and Corfu will get out of the way. - - But orderless search terms can contain arbitrary characters; they are - also interpreted as regular expressions. To use orderless, set - `corfu-separator' (a space, by default) to the primary character of - your orderless component separator. - - Then, when a new orderless component is desired, use `M-SPC' - (`corfu-insert-separator') to enter the first component separator in - the input, and arbitrary orderless search terms and new separators can - be entered thereafter. - - To treat the entire input as Orderless input, you can set the - customization option `corfu-quit-at-boundary' to nil. This disables - the predicate which checks if the current completion boundary has been - left. In contrast, if you always want to quit at the boundary, set - `corfu-quit-at-boundary' to t. By default `corfu-quit-at-boundary' is - set to `separator' which quits at completion boundaries as long as no - separator has been inserted with `corfu-insert-separator'. - - Finally, there exists the user option `corfu-quit-no-match' which is - set to `separator' by default. With this setting Corfu stays alive as - soon as you start advanced filtering with a `corfu-separator' even if - there are no matches, for example due to a typo. As long as no - separator character has been inserted with `corfu-insert-separator', - Corfu will still quit if there are no matches. This ensures that the - Corfu popup goes away quickly if completion is not possible. - - In the following we show two configurations, one which works best with - auto completion and one which may work better with manual completion - if you prefer to always use `SPC' to separate the Orderless - components. - - ┌──── - │ ;; Auto completion example - │ (use-package corfu - │ :custom - │ (corfu-auto t) ;; Enable auto completion - │ ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space - │ :bind - │ ;; Another key binding can be used, such as S-SPC. - │ ;; (:map corfu-map ("M-SPC" . corfu-insert-separator)) - │ :init - │ (global-corfu-mode)) - │ - │ ;; Manual completion example - │ (use-package corfu - │ :custom - │ ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space - │ :bind - │ ;; Configure SPC for separator insertion - │ (:map corfu-map ("SPC" . corfu-insert-separator)) - │ :init - │ (global-corfu-mode)) - └──── - - -[Orderless] <https://github.com/oantolin/orderless> - - -2.5 TAB-only completion -─────────────────────── - - By default, Corfu steals both the `RET' and `TAB' keys, when the Corfu - popup is open. This can feel intrusive, in particular in combination - with auto completion. `RET' may accidentally commit an automatically - selected candidate, while you actually wanted to start a new line. As - an alternative we can unbind the `RET' key completely from `corfu-map' - or reserve the `RET' key only in shell modes. - - ┌──── - │ ;; TAB-only configuration - │ (use-package corfu - │ :custom - │ (corfu-auto t) ;; Enable auto completion - │ (corfu-preselect 'directory) ;; Select the first candidate, except for directories - │ - │ ;; Free the RET key for less intrusive behavior. - │ :bind - │ (:map corfu-map - │ ;; Option 1: Unbind RET completely - │ ;;; ("RET" . nil) - │ ;; Option 2: Use RET only in shell modes - │ ("RET" . (menu-item "" nil :filter corfu-insert-shell-filter))) - │ - │ :init - │ (global-corfu-mode)) - │ - │ (defun corfu-insert-shell-filter (&optional _) - │ "Insert completion candidate and send when inside comint/eshell." - │ (when (or (derived-mode-p 'eshell-mode) (derived-mode-p 'comint-mode)) - │ (lambda () - │ (interactive) - │ (corfu-insert) - │ ;; `corfu-send-shell' was defined above - │ (corfu-send-shell)))) - └──── - - -2.6 TAB-and-Go completion -───────────────────────── - - You may be interested in configuring Corfu in TAB-and-Go - style. Pressing TAB moves to the next candidate and further input will - then commit the selection. Note that further input will not expand - snippets or templates, which may not be desired but which leads - overall to a more predictable behavior. In order to force snippet - expansion, confirm a candidate explicitly with `RET'. - - ┌──── - │ (use-package corfu - │ ;; TAB-and-Go customizations - │ :custom - │ (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' - │ (corfu-preselect 'prompt) ;; Always preselect the prompt - │ - │ ;; Use TAB for cycling, default is `corfu-complete'. - │ :bind - │ (:map corfu-map - │ ("TAB" . corfu-next) - │ ([tab] . corfu-next) - │ ("S-TAB" . corfu-previous) - │ ([backtab] . corfu-previous)) - │ - │ :init - │ (global-corfu-mode)) - └──── - - -2.7 Transfer completion to the minibuffer -───────────────────────────────────────── - - Sometimes it is useful to transfer the Corfu completion session to the - minibuffer, since the minibuffer offers richer interaction - features. In particular, [Embark] is available in the minibuffer, such - that you can act on the candidates or export/collect the candidates to - a separate buffer. We could add Corfu support to Embark in the future, - such that export/collect is possible directly from Corfu. But in my - opinion having the ability to transfer the Corfu completion to the - minibuffer is an even better feature, since further completion can be - performed there. - - The command `corfu-move-to-minibuffer' is defined here in terms of - `consult-completion-in-region', which uses the minibuffer completion - UI via `completing-read'. - - ┌──── - │ (defun corfu-move-to-minibuffer () - │ (interactive) - │ (when completion-in-region--data - │ (let ((completion-extra-properties corfu--extra) - │ completion-cycle-threshold completion-cycling) - │ (apply #'consult-completion-in-region completion-in-region--data)))) - │ (keymap-set corfu-map "M-m" #'corfu-move-to-minibuffer) - │ (add-to-list 'corfu-continue-commands #'corfu-move-to-minibuffer) - └──── - - -[Embark] <https://github.com/oantolin/embark> - - -3 Key bindings -══════════════ - - Corfu uses a transient keymap `corfu-map' which is active while the - popup is shown. The keymap defines the following remappings and - bindings: - - • `move-beginning-of-line' -> `corfu-prompt-beginning' - • `move-end-of-line' -> `corfu-prompt-end' - • `beginning-of-buffer' -> `corfu-first' - • `end-of-buffer' -> `corfu-last' - • `scroll-down-command' -> `corfu-scroll-down' - • `scroll-up-command' -> `corfu-scroll-up' - • `next-line', `down', `M-n' -> `corfu-next' - • `previous-line', `up', `M-p' -> `corfu-previous' - • `completion-at-point', `TAB' -> `corfu-complete' - • `RET' -> `corfu-insert' - • `M-g' -> `corfu-info-location' - • `M-h' -> `corfu-info-documentation' - • `M-SPC' -> `corfu-insert-separator' - • `C-g' -> `corfu-quit' - • `keyboard-escape-quit' -> `corfu-reset' - - -4 Extensions -════════════ - - We maintain small extension packages to Corfu in this repository in - the subdirectory [extensions/]. The extensions are installed together - with Corfu if you pull the package from ELPA. The extensions are - inactive by default and can be enabled manually if - desired. Furthermore it is possible to install all of the files - separately, both `corfu.el' and the `corfu-*.el' extensions. Currently - the following extensions come with the Corfu ELPA package: - - • [corfu-echo]: `corfu-echo-mode' displays a brief candidate - documentation in the echo area. - • [corfu-history]: `corfu-history-mode' remembers selected candidates - and sorts the candidates by their history position. - • [corfu-indexed]: `corfu-indexed-mode' allows you to select indexed - candidates with prefix arguments. - • [corfu-info]: Actions to access the candidate location and - documentation. - • [corfu-popupinfo]: Display candidate documentation or source in a - popup next to the candidate menu. - • [corfu-quick]: Commands to select using Avy-style quick keys. - - See the Commentary of those files for configuration details. - - -[extensions/] <https://github.com/minad/corfu/tree/main/extensions> - -[corfu-echo] -<https://github.com/minad/corfu/blob/main/extensions/corfu-echo.el> - -[corfu-history] -<https://github.com/minad/corfu/blob/main/extensions/corfu-history.el> - -[corfu-indexed] -<https://github.com/minad/corfu/blob/main/extensions/corfu-indexed.el> - -[corfu-info] -<https://github.com/minad/corfu/blob/main/extensions/corfu-info.el> - -[corfu-popupinfo] -<https://github.com/minad/corfu/blob/main/extensions/corfu-popupinfo.el> - -[corfu-quick] -<https://github.com/minad/corfu/blob/main/extensions/corfu-quick.el> - - -5 Complementary packages -════════════════════════ - - Corfu works well together with all packages providing code completion - via the `completion-at-point-functions'. Many modes and packages - already provide a Capf out of the box. Nevertheless you may want to - look into complementary packages to enhance your setup. - - • [corfu-terminal]: The corfu-terminal package provides an - overlay-based display for Corfu, such that you can use Corfu in - terminal Emacs. - - • [corfu-candidate-overlay]: Shows as-you-type auto-suggestion - candidate overlay with a visual indication of whether there are many - or exactly one candidate available (works only with `corfu-auto' - disabled). - - • [Orderless]: Corfu supports completion styles, including the - advanced `orderless' completion style, where the filter expressions - are separated by spaces or another character (see - `corfu-separator'). - - • [Cape]: Provides additional Capf backends and `completion-in-region' - commands. Among others, the package supplies the file completion - backend `cape-file' and the Dabbrev backend `cape-dabbrev'. Cape - provides the `cape-company-to-capf' adapter to reuse Company - backends in Corfu. - - • [nerd-icons-corfu], [kind-icon]: Icons are supported by Corfu via - external packages. The nerd-icons-corfu package relies on the Nerd - icon font, which is even supported on terminal, while kind-icon uses - SVGs from monochromatic icon sets. - - • [pcmpl-args]: Extend the Eshell/Shell Pcomplete mechanism with - support for many commands. Similar to the Fish shell, pcmpl-args - uses man page parsing to dynamically retrieve the completions and - helpful annotations. - - • [Tempel]: Tiny template/snippet package with templates in Lisp - syntax, which can be used in conjunction with Corfu. - - • [Vertico]: You may also want to look into my Vertico - package. Vertico is the minibuffer completion counterpart of Corfu. - - -[corfu-terminal] <https://codeberg.org/akib/emacs-corfu-terminal> - -[corfu-candidate-overlay] -<https://code.bsdgeek.org/adam/corfu-candidate-overlay> - -[Orderless] <https://github.com/oantolin/orderless> - -[Cape] <https://github.com/minad/cape> - -[nerd-icons-corfu] <https://github.com/LuigiPiucco/nerd-icons-corfu> - -[kind-icon] <https://github.com/jdtsmith/kind-icon> - -[pcmpl-args] <https://github.com/JonWaltman/pcmpl-args.el> - -[Tempel] <https://github.com/minad/tempel> - -[Vertico] <https://github.com/minad/vertico> - - -6 Alternatives -══════════════ - - • [Company]: Company is a widely used and mature completion package, - which implements a similar UI as Corfu. While Corfu relies - exclusively on the standard Emacs completion API (Capfs), Company - defines its own API for the backends. Company includes its own - completion backends, following its own API, which are incompatible - with the Emacs completion infrastructure. Company provides an - adapter `company-capf' to handle Capfs as a Company backend. As a - result of this design, Company is a more complex package than - Corfu. Company by default uses overlays for the popup in contrast to - the child frames used by Corfu. Overall both packages work well, but - Company integrates less tightly with Emacs. The `completion-styles' - support is more limited and the `completion-at-point' command and - the `completion-in-region' function do not invoke Company. - - • [consult-completion-in-region]: The Consult package provides the - function `consult-completion-in-region' which can be set as - `completion-in-region-function' such that it handles - `completion-at-point'. The function works by transferring the - in-buffer completion to the minibuffer. In the minibuffer, the - minibuffer completion UI, for example [Vertico] takes over. If you - prefer to perform all your completions in the minibuffer - `consult-completion-in-region' is your best option. - - -[Company] <https://github.com/company-mode/company-mode> - -[consult-completion-in-region] <https://github.com/minad/consult> - -[Vertico] <https://github.com/minad/vertico> - - -7 Debugging Corfu -═════════════════ - - When you observe an error in the `corfu--post-command' post command - hook, you should install an advice to enforce debugging. This allows - you to obtain a stack trace in order to narrow down the location of - the error. The reason is that post command hooks are automatically - disabled (and not debugged) by Emacs. Otherwise Emacs would become - unusable, given that the hooks are executed after every command. - - ┌──── - │ (setq debug-on-error t) - │ - │ (defun force-debug (func &rest args) - │ (condition-case e - │ (apply func args) - │ ((debug error) (signal (car e) (cdr e))))) - │ - │ (advice-add #'corfu--post-command :around #'force-debug) - └──── - - When Capfs do not yield the expected result you can use - `cape-capf-debug' to add debug messages to a Capf. The Capf will then - produce a completion log in the messages buffer. - - ┌──── - │ (setq completion-at-point-functions (list (cape-capf-debug #'cape-dict))) - └──── - - -8 Contributions -═══════════════ - - Since this package is part of [GNU ELPA] contributions require a - copyright assignment to the FSF. - - -[GNU ELPA] <https://elpa.gnu.org/packages/corfu.html> diff --git a/elpa/corfu-1.0/README.org b/elpa/corfu-1.0/README.org @@ -1,616 +0,0 @@ -#+title: corfu.el - COmpletion in Region FUnction -#+author: Daniel Mendler -#+language: en -#+export_file_name: corfu.texi -#+texinfo_dir_category: Emacs misc features -#+texinfo_dir_title: Corfu: (corfu). -#+texinfo_dir_desc: COmpletion in Region FUnction - -#+html: <a href="https://www.gnu.org/software/emacs/"><img alt="GNU Emacs" src="https://github.com/minad/corfu/blob/screenshots/emacs.svg?raw=true"/></a> -#+html: <a href="https://elpa.gnu.org/packages/corfu.html"><img alt="GNU ELPA" src="https://elpa.gnu.org/packages/corfu.svg"/></a> -#+html: <a href="https://elpa.gnu.org/devel/corfu.html"><img alt="GNU-devel ELPA" src="https://elpa.gnu.org/devel/corfu.svg"/></a> -#+html: <a href="https://melpa.org/#/corfu"><img alt="MELPA" src="https://melpa.org/packages/corfu-badge.svg"/></a> -#+html: <a href="https://stable.melpa.org/#/corfu"><img alt="MELPA Stable" src="https://stable.melpa.org/packages/corfu-badge.svg"/></a> - -Corfu enhances in-buffer completion with a small completion popup. The current -candidates are shown in a popup below or above the point. The candidates can be -selected by moving up and down. Corfu is the minimalistic in-buffer completion -counterpart of the [[https://github.com/minad/vertico][Vertico]] minibuffer UI. - -Corfu is a small package, which relies on the Emacs completion facilities and -concentrates on providing a polished completion UI. In-buffer completion UIs in -Emacs can hook into ~completion-in-region~, which implements the interaction with -the user. Completions at point are either provided by commands like -~dabbrev-completion~ or by pluggable backends (~completion-at-point-functions~, -Capfs) and are then passed to ~completion-in-region~. Many programming, text and -shell major modes implement a Capf. Corfu does not include its own completion -backends. The Emacs built-in Capfs and the Capfs provided by third-party -programming language packages are often sufficient. Additional Capfs and -completion utilities are provided by the [[https://github.com/minad/cape][Cape]] package. - -*NOTE*: Corfu uses child frames to show the popup and falls back to the default -setting of the ~completion-in-region-function~ on non-graphical displays. If you -want to use Corfu in the terminal, install the package [[https://codeberg.org/akib/emacs-corfu-terminal][corfu-terminal]], which -provides an alternative overlay-based display. - -#+html: <img src="https://github.com/minad/corfu/blob/screenshots/light.png?raw=true"> - -#+html: <img src="https://github.com/minad/corfu/blob/screenshots/dark.png?raw=true"> - -#+html: <img src="https://github.com/minad/corfu/blob/screenshots/popupinfo-light.png?raw=true"> - -#+html: <img src="https://github.com/minad/corfu/blob/screenshots/popupinfo-dark.png?raw=true"> - -#+toc: headlines 8 - -* Features - -- Timer-based auto-completions (/off/ by default, set ~corfu-auto~). -- Popup display with scrollbar indicator and arrow key navigation. -- The popup can be summoned explicitly by pressing =TAB= at any time. -- The current candidate is inserted with =TAB= and selected with =RET=. -- Candidate sorting by prefix, string length and alphabetically. -- The selected candidate is previewed (configurable via ~corfu-preview-current~). -- The selected candidate is automatically committed on further input by default. - (configurable via ~corfu-preview-current~). -- Supports the [[https://github.com/oantolin/orderless][Orderless]] completion style. The filter string can contain - arbitrary characters, after inserting a space via =M-SPC= (configurable via - ~corfu-quit-at-boundary~ and ~corfu-separator~). -- Lazy completion candidate highlighting for performance. -- Support for candidate annotations (=annotation-function=, =affixation-function=). -- Deprecated candidates are displayed as crossed out. -- Icons can be provided by an external package via margin formatter functions. -- Rich set of extensions: Quick keys, Index keys, Sorting by history, Candidate - documentation in echo area, popup or separate buffer. - -* Installation and Configuration - -Corfu is available from [[https://elpa.gnu.org/packages/corfu.html][GNU ELPA]], such that it can be installed directly via -~package-install~. After installation, the global minor mode can be enabled with -=M-x global-corfu-mode=. In order to configure Corfu and other packages in your -init.el, you may want to use ~use-package~. - -Corfu is highly flexible and customizable via ~corfu-*~ customization variables, -such that you can adapt it precisely to your requirements. However in order to -quickly try out the Corfu completion package, it should be sufficient to -activate ~global-corfu-mode~. You can experiment with manual completion for -example in an Elisp buffer or in an Eshell or Shell buffer. For auto completion, -set ~corfu-auto~ to t before turning on ~global-corfu-mode~. - -Here is an example configuration: - -#+begin_src emacs-lisp -(use-package corfu - ;; Optional customizations - ;; :custom - ;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' - ;; (corfu-auto t) ;; Enable auto completion - ;; (corfu-separator ?\s) ;; Orderless field separator - ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary - ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match - ;; (corfu-preview-current nil) ;; Disable current candidate preview - ;; (corfu-preselect 'prompt) ;; Preselect the prompt - ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches - ;; (corfu-scroll-margin 5) ;; Use scroll margin - - ;; Enable Corfu only for certain modes. - ;; :hook ((prog-mode . corfu-mode) - ;; (shell-mode . corfu-mode) - ;; (eshell-mode . corfu-mode)) - - ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can - ;; be used globally (M-/). See also the customization variable - ;; `global-corfu-modes' to exclude certain modes. - :init - (global-corfu-mode)) - -;; A few more useful configurations... -(use-package emacs - :init - ;; TAB cycle if there are only few candidates - (setq completion-cycle-threshold 3) - - ;; Emacs 28: Hide commands in M-x which do not apply to the current mode. - ;; Corfu commands are hidden, since they are not supposed to be used via M-x. - ;; (setq read-extended-command-predicate - ;; #'command-completion-default-include-p) - - ;; Enable indentation+completion using the TAB key. - ;; `completion-at-point' is often bound to M-TAB. - (setq tab-always-indent 'complete)) -#+end_src - -Dabbrev completion is based on =completion-in-region= and can be used with Corfu. -You may want to swap the =dabbrev-completion= with the =dabbrev-expand= key for -easier access, if you prefer completion. Also take a look at the =cape-dabbrev= -completion at point function provided by my [[https://github.com/minad/cape][Cape]] package. - -#+begin_src emacs-lisp -;; Use Dabbrev with Corfu! -(use-package dabbrev - ;; Swap M-/ and C-M-/ - :bind (("M-/" . dabbrev-completion) - ("C-M-/" . dabbrev-expand)) - ;; Other useful Dabbrev configurations. - :custom - (dabbrev-ignored-buffer-regexps '("\\.\\(?:pdf\\|jpe?g\\|png\\)\\'"))) -#+end_src - -If you start to configure the package more deeply, I recommend to give the -Orderless completion style a try for filtering. Orderless completion is -different from the familiar prefix TAB completion. Corfu can be used with the -default completion styles. The use of Orderless is not a necessity. - -#+begin_src emacs-lisp -;; Optionally use the `orderless' completion style. -(use-package orderless - :init - ;; Configure a custom style dispatcher (see the Consult wiki) - ;; (setq orderless-style-dispatchers '(+orderless-dispatch) - ;; orderless-component-separator #'orderless-escapable-split-on-space) - (setq completion-styles '(orderless basic) - completion-category-defaults nil - completion-category-overrides '((file (styles partial-completion))))) -#+end_src - -The =basic= completion style is specified as fallback in addition to =orderless= in -order to ensure that completion commands which rely on dynamic completion -tables, e.g., ~completion-table-dynamic~ or ~completion-table-in-turn~, work -correctly. See =+orderless-dispatch= in the [[https://github.com/minad/consult/wiki][Consult wiki]] for an advanced Orderless -style dispatcher. Additionally enable =partial-completion= for file path -expansion. =partial-completion= is important for file wildcard support. Multiple -files can be opened at once with =find-file= if you enter a wildcard. You may also -give the =initials= completion style a try. - -See also the [[https://github.com/minad/corfu/wiki][Corfu Wiki]] and the [[https://github.com/minad/cape][Cape manual]] for additional Capf configuration -tips. For more general documentation read the chapter about completion in the -[[https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion.html][Emacs manual]]. If you want to create your own Capfs, you can find documentation -about completion in the [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion.html][Elisp manual]]. - -** Auto completion - -Auto completion is disabled by default, but can be enabled by setting ~corfu-auto~ -to t. Furthermore you may want to configure Corfu to quit completion eagerly, -such that the completion popup stays out of your way when it appeared -unexpectedly. - -#+begin_src emacs-lisp -;; Enable auto completion and configure quitting -(setq corfu-auto t - corfu-quit-no-match 'separator) ;; or t -#+end_src - -I suggest to experiment with the various settings and key bindings to find a -configuration which works for you. There is no one perfect configuration which -fits all. Some people like auto completion, some like manual completion, some -want to cycle with TAB and some with the arrow keys. - -In case you like auto completion settings, where the completion popup appears -immediately, better use a cheap completion style like =basic=, which performs -prefix filtering. In this case Corfu completion should still be fast in buffers -with efficient completion backends. You can try the following settings in an -Elisp buffer or the Emacs scratch buffer. Note that such settings can slow down -Emacs due to the high load on the Lisp runtime and garbage collector. - -#+begin_src emacs-lisp -(setq-local corfu-auto t - corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED - corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED - completion-styles '(basic)) -#+end_src - -If you want to combine fast prefix filtering and Orderless filtering you can -still do that by defining a custom Orderless completion style via -=orderless-define-completion-style=. We use a custom style dispatcher, which -enables efficient prefix filtering for input shorter than 4 characters. Note -that such a setup is advanced. Please refer to the Orderless documentation and -source code for further details. - -#+begin_src emacs-lisp -(defun orderless-fast-dispatch (word index total) - (and (= index 0) (= total 1) (length< word 4) - `(orderless-regexp . ,(concat "^" (regexp-quote word))))) - -(orderless-define-completion-style orderless-fast - (orderless-style-dispatchers '(orderless-fast-dispatch)) - (orderless-matching-styles '(orderless-literal orderless-regexp))) - -(setq-local corfu-auto t - corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED - corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED - completion-styles '(orderless-fast basic)) -#+end_src - -** Completing in the minibuffer - -Corfu can be used for completion in the minibuffer, since it relies on child -frames to display the candidates. By default, ~global-corfu-mode~ does not -activate ~corfu-mode~ in the minibuffer, to avoid interference with specialised -minibuffer completion UIs like Vertico or Mct. However you may still want to -enable Corfu completion for commands like ~M-:~ (~eval-expression~) or ~M-!~ -(~shell-command~), which read from the minibuffer. Activate ~corfu-mode~ only if -~completion-at-point~ is bound in the minibuffer-local keymap to achieve this -effect. - -#+begin_src emacs-lisp -(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-auto nil) ;; Enable/disable auto completion - (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) -#+end_src - -You can also enable Corfu more generally for every minibuffer, as long as no -completion UI is active. In the following example we check for Mct and Vertico. -Furthermore we ensure that Corfu is not enabled if a password is read from the -minibuffer. - -#+begin_src emacs-lisp -(defun corfu-enable-always-in-minibuffer () - "Enable Corfu in the minibuffer if Vertico/Mct are not active." - (unless (or (bound-and-true-p mct--active) - (bound-and-true-p vertico--input) - (eq (current-local-map) read-passwd-map)) - ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion - (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-always-in-minibuffer 1) -#+end_src - -** Completing in the Eshell or Shell - -When completing in the Eshell I recommend conservative local settings without -auto completion, such that the completion behavior is similar to widely used -shells like Bash, Zsh or Fish. - -#+begin_src emacs-lisp -(add-hook 'eshell-mode-hook - (lambda () - (setq-local corfu-auto nil) - (corfu-mode))) -#+end_src - -When pressing =RET= while the Corfu popup is visible, the ~corfu-insert~ command -will be invoked. This command does inserts the currently selected candidate, but -it does not send the prompt input to Eshell or the Comint process. Therefore you -often have to press =RET= twice which feels like an unnecessary double -confirmation. Fortunately it is easy to improve this! In my configuration I -define the advice ~corfu-send-shell~ which sends the candidate after insertion. - -#+begin_src emacs-lisp -(defun corfu-send-shell (&rest _) - "Send completion candidate when inside comint/eshell." - (cond - ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) - (eshell-send-input)) - ((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) - (comint-send-input)))) - -(advice-add #'corfu-insert :after #'corfu-send-shell) -#+end_src - -Shell completion uses the flexible Pcomplete mechanism internally, which allows -you to program the completions per shell command. If you want to know more, look -into this [[https://www.masteringemacs.org/article/pcomplete-context-sensitive-completion-emacs][blog post]], which shows how to configure Pcomplete for git commands. - -You can try the [[https://github.com/JonWaltman/pcmpl-args.el][pcmpl-args]] package which extends Pcomplete with completion -support and helpful annotation support for more commands. Similar to the Fish -shell, =pcmpl-args= uses man page parsing and ~--help~ output parsing to dynamically -generate completions. Since Emacs 29, Pcomplete offers the =pcomplete-from-help= -function which parses the ~--help~ output of a command and produces completions. -This Emacs 29 functionality is not completely equivalent. For example it does -not display annotations in Eshell, but this may get fixed in Emacs 30. - -Pcomplete has a few bugs on Emacs 28 and older. We can work around the issues -with the [[https://github.com/minad/cape][Cape]] library (Completion at point extensions). Cape provides wrappers -which sanitize the Pcomplete function. If you use Emacs 28 or older installing -these advices is recommended such that Pcomplete works properly. On Emacs 29 the -advices should not be necessary anymore, since most of the relevant bugs have -been fixed. I therefore recommend to remove the advices on Emacs 29 and -eventually report any remaining Pcomplete issues upstream, such that they can be -fixed. - -#+begin_src emacs-lisp -;; The advices are only needed on Emacs 28 and older. -(when (< emacs-major-version 29) - ;; Silence the pcomplete capf, no errors or messages! - (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent) - - ;; Ensure that pcomplete does not write to the buffer - ;; and behaves as a pure `completion-at-point-function'. - (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)) -#+end_src - -** Orderless completion - -[[https://github.com/oantolin/orderless][Orderless]] is an advanced completion style that supports multi-component search -filters separated by a configurable character (space, by default). Normally, -entering characters like space which lie outside the completion region -boundaries (words, typically) causes Corfu to quit. This behavior is helpful -with auto-completion, which may pop-up when not desired, e.g. on entering a new -variable name. Just keep typing and Corfu will get out of the way. - -But orderless search terms can contain arbitrary characters; they are also -interpreted as regular expressions. To use orderless, set ~corfu-separator~ (a -space, by default) to the primary character of your orderless component -separator. - -Then, when a new orderless component is desired, use =M-SPC= -(~corfu-insert-separator~) to enter the first component separator in the input, -and arbitrary orderless search terms and new separators can be entered -thereafter. - -To treat the entire input as Orderless input, you can set the customization -option ~corfu-quit-at-boundary~ to nil. This disables the predicate which checks -if the current completion boundary has been left. In contrast, if you always -want to quit at the boundary, set ~corfu-quit-at-boundary~ to t. By default -~corfu-quit-at-boundary~ is set to ~separator~ which quits at completion boundaries -as long as no separator has been inserted with ~corfu-insert-separator~. - -Finally, there exists the user option ~corfu-quit-no-match~ which is set to -=separator= by default. With this setting Corfu stays alive as soon as you start -advanced filtering with a ~corfu-separator~ even if there are no matches, for -example due to a typo. As long as no separator character has been inserted with -~corfu-insert-separator~, Corfu will still quit if there are no matches. This -ensures that the Corfu popup goes away quickly if completion is not possible. - -In the following we show two configurations, one which works best with auto -completion and one which may work better with manual completion if you prefer to -always use =SPC= to separate the Orderless components. - - #+begin_src emacs-lisp -;; Auto completion example -(use-package corfu - :custom - (corfu-auto t) ;; Enable auto completion - ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space - :bind - ;; Another key binding can be used, such as S-SPC. - ;; (:map corfu-map ("M-SPC" . corfu-insert-separator)) - :init - (global-corfu-mode)) - -;; Manual completion example -(use-package corfu - :custom - ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space - :bind - ;; Configure SPC for separator insertion - (:map corfu-map ("SPC" . corfu-insert-separator)) - :init - (global-corfu-mode)) -#+end_src - -** TAB-only completion - -By default, Corfu steals both the ~RET~ and ~TAB~ keys, when the Corfu popup is -open. This can feel intrusive, in particular in combination with auto -completion. ~RET~ may accidentally commit an automatically selected candidate, -while you actually wanted to start a new line. As an alternative we can unbind -the ~RET~ key completely from ~corfu-map~ or reserve the ~RET~ key only in shell -modes. - -#+begin_src emacs-lisp -;; TAB-only configuration -(use-package corfu - :custom - (corfu-auto t) ;; Enable auto completion - (corfu-preselect 'directory) ;; Select the first candidate, except for directories - - ;; Free the RET key for less intrusive behavior. - :bind - (:map corfu-map - ;; Option 1: Unbind RET completely - ;;; ("RET" . nil) - ;; Option 2: Use RET only in shell modes - ("RET" . (menu-item "" nil :filter corfu-insert-shell-filter))) - - :init - (global-corfu-mode)) - -(defun corfu-insert-shell-filter (&optional _) - "Insert completion candidate and send when inside comint/eshell." - (when (or (derived-mode-p 'eshell-mode) (derived-mode-p 'comint-mode)) - (lambda () - (interactive) - (corfu-insert) - ;; `corfu-send-shell' was defined above - (corfu-send-shell)))) -#+end_src - -** TAB-and-Go completion - -You may be interested in configuring Corfu in TAB-and-Go style. Pressing TAB -moves to the next candidate and further input will then commit the selection. -Note that further input will not expand snippets or templates, which may not be -desired but which leads overall to a more predictable behavior. In order to -force snippet expansion, confirm a candidate explicitly with ~RET~. - -#+begin_src emacs-lisp -(use-package corfu - ;; TAB-and-Go customizations - :custom - (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' - (corfu-preselect 'prompt) ;; Always preselect the prompt - - ;; Use TAB for cycling, default is `corfu-complete'. - :bind - (:map corfu-map - ("TAB" . corfu-next) - ([tab] . corfu-next) - ("S-TAB" . corfu-previous) - ([backtab] . corfu-previous)) - - :init - (global-corfu-mode)) -#+end_src - -** Transfer completion to the minibuffer - -Sometimes it is useful to transfer the Corfu completion session to the -minibuffer, since the minibuffer offers richer interaction features. In -particular, [[https://github.com/oantolin/embark][Embark]] is available in the minibuffer, such that you can act on the -candidates or export/collect the candidates to a separate buffer. We could add -Corfu support to Embark in the future, such that export/collect is possible -directly from Corfu. But in my opinion having the ability to transfer the Corfu -completion to the minibuffer is an even better feature, since further completion -can be performed there. - -The command ~corfu-move-to-minibuffer~ is defined here in terms of -~consult-completion-in-region~, which uses the minibuffer completion UI via -~completing-read~. - -#+begin_src emacs-lisp -(defun corfu-move-to-minibuffer () - (interactive) - (when completion-in-region--data - (let ((completion-extra-properties corfu--extra) - completion-cycle-threshold completion-cycling) - (apply #'consult-completion-in-region completion-in-region--data)))) -(keymap-set corfu-map "M-m" #'corfu-move-to-minibuffer) -(add-to-list 'corfu-continue-commands #'corfu-move-to-minibuffer) -#+end_src - -* Key bindings - -Corfu uses a transient keymap ~corfu-map~ which is active while the popup is -shown. The keymap defines the following remappings and bindings: - -- ~move-beginning-of-line~ -> ~corfu-prompt-beginning~ -- ~move-end-of-line~ -> ~corfu-prompt-end~ -- ~beginning-of-buffer~ -> ~corfu-first~ -- ~end-of-buffer~ -> ~corfu-last~ -- ~scroll-down-command~ -> ~corfu-scroll-down~ -- ~scroll-up-command~ -> ~corfu-scroll-up~ -- ~next-line~, =down=, =M-n= -> ~corfu-next~ -- ~previous-line~, =up=, =M-p= -> ~corfu-previous~ -- ~completion-at-point~, =TAB= -> ~corfu-complete~ -- =RET= -> ~corfu-insert~ -- =M-g= -> ~corfu-info-location~ -- =M-h= -> ~corfu-info-documentation~ -- =M-SPC= -> ~corfu-insert-separator~ -- =C-g= -> ~corfu-quit~ -- ~keyboard-escape-quit~ -> ~corfu-reset~ - -* Extensions -:properties: -:custom_id: extensions -:end: - -We maintain small extension packages to Corfu in this repository in the -subdirectory [[https://github.com/minad/corfu/tree/main/extensions][extensions/]]. The extensions are installed together with Corfu if -you pull the package from ELPA. The extensions are inactive by default and can -be enabled manually if desired. Furthermore it is possible to install all of the -files separately, both ~corfu.el~ and the ~corfu-*.el~ extensions. Currently the -following extensions come with the Corfu ELPA package: - -- [[https://github.com/minad/corfu/blob/main/extensions/corfu-echo.el][corfu-echo]]: =corfu-echo-mode= displays a brief candidate documentation in the - echo area. -- [[https://github.com/minad/corfu/blob/main/extensions/corfu-history.el][corfu-history]]: =corfu-history-mode= remembers selected candidates and sorts the - candidates by their history position. -- [[https://github.com/minad/corfu/blob/main/extensions/corfu-indexed.el][corfu-indexed]]: =corfu-indexed-mode= allows you to select indexed candidates with - prefix arguments. -- [[https://github.com/minad/corfu/blob/main/extensions/corfu-info.el][corfu-info]]: Actions to access the candidate location and documentation. -- [[https://github.com/minad/corfu/blob/main/extensions/corfu-popupinfo.el][corfu-popupinfo]]: Display candidate documentation or source in a popup next to - the candidate menu. -- [[https://github.com/minad/corfu/blob/main/extensions/corfu-quick.el][corfu-quick]]: Commands to select using Avy-style quick keys. - -See the Commentary of those files for configuration details. - -* Complementary packages - -Corfu works well together with all packages providing code completion via the -~completion-at-point-functions~. Many modes and packages already provide a Capf -out of the box. Nevertheless you may want to look into complementary packages to -enhance your setup. - -- [[https://codeberg.org/akib/emacs-corfu-terminal][corfu-terminal]]: The corfu-terminal package provides an overlay-based display - for Corfu, such that you can use Corfu in terminal Emacs. - -- [[https://code.bsdgeek.org/adam/corfu-candidate-overlay][corfu-candidate-overlay]]: Shows as-you-type auto-suggestion candidate overlay - with a visual indication of whether there are many or exactly one candidate - available (works only with =corfu-auto= disabled). - -- [[https://github.com/oantolin/orderless][Orderless]]: Corfu supports completion styles, including the advanced =orderless= - completion style, where the filter expressions are separated by spaces or - another character (see ~corfu-separator~). - -- [[https://github.com/minad/cape][Cape]]: Provides additional Capf backends and =completion-in-region= commands. - Among others, the package supplies the file completion backend =cape-file= and - the Dabbrev backend =cape-dabbrev=. Cape provides the ~cape-company-to-capf~ - adapter to reuse Company backends in Corfu. - -- [[https://github.com/LuigiPiucco/nerd-icons-corfu][nerd-icons-corfu]], [[https://github.com/jdtsmith/kind-icon][kind-icon]]: Icons are supported by Corfu via external - packages. The nerd-icons-corfu package relies on the Nerd icon font, which is - even supported on terminal, while kind-icon uses SVGs from monochromatic icon - sets. - -- [[https://github.com/JonWaltman/pcmpl-args.el][pcmpl-args]]: Extend the Eshell/Shell Pcomplete mechanism with support for many - commands. Similar to the Fish shell, pcmpl-args uses man page parsing to - dynamically retrieve the completions and helpful annotations. - -- [[https://github.com/minad/tempel][Tempel]]: Tiny template/snippet package with templates in Lisp syntax, which - can be used in conjunction with Corfu. - -- [[https://github.com/minad/vertico][Vertico]]: You may also want to look into my Vertico package. Vertico is the - minibuffer completion counterpart of Corfu. - -* Alternatives - -- [[https://github.com/company-mode/company-mode][Company]]: Company is a widely used and mature completion package, which - implements a similar UI as Corfu. While Corfu relies exclusively on the - standard Emacs completion API (Capfs), Company defines its own API for the - backends. Company includes its own completion backends, following its own API, - which are incompatible with the Emacs completion infrastructure. Company - provides an adapter ~company-capf~ to handle Capfs as a Company backend. As a - result of this design, Company is a more complex package than Corfu. Company - by default uses overlays for the popup in contrast to the child frames used by - Corfu. Overall both packages work well, but Company integrates less tightly - with Emacs. The ~completion-styles~ support is more limited and the - ~completion-at-point~ command and the ~completion-in-region~ function do not - invoke Company. - -- [[https://github.com/minad/consult][consult-completion-in-region]]: The Consult package provides the function - ~consult-completion-in-region~ which can be set as ~completion-in-region-function~ - such that it handles ~completion-at-point~. The function works by transferring - the in-buffer completion to the minibuffer. In the minibuffer, the minibuffer - completion UI, for example [[https://github.com/minad/vertico][Vertico]] takes over. If you prefer to perform all - your completions in the minibuffer ~consult-completion-in-region~ is your best - option. - -* Debugging Corfu - -When you observe an error in the =corfu--post-command= post command hook, you -should install an advice to enforce debugging. This allows you to obtain a stack -trace in order to narrow down the location of the error. The reason is that post -command hooks are automatically disabled (and not debugged) by Emacs. Otherwise -Emacs would become unusable, given that the hooks are executed after every -command. - -#+begin_src emacs-lisp -(setq debug-on-error t) - -(defun force-debug (func &rest args) - (condition-case e - (apply func args) - ((debug error) (signal (car e) (cdr e))))) - -(advice-add #'corfu--post-command :around #'force-debug) -#+end_src - -When Capfs do not yield the expected result you can use ~cape-capf-debug~ to add -debug messages to a Capf. The Capf will then produce a completion log in the -messages buffer. - -#+begin_src emacs-lisp -(setq completion-at-point-functions (list (cape-capf-debug #'cape-dict))) -#+end_src - -* Contributions - -Since this package is part of [[https://elpa.gnu.org/packages/corfu.html][GNU ELPA]] contributions require a copyright -assignment to the FSF. diff --git a/elpa/corfu-1.0/corfu-echo.el b/elpa/corfu-1.0/corfu-echo.el @@ -1,108 +0,0 @@ -;;; corfu-echo.el --- Show candidate documentation in echo area -*- lexical-binding: t -*- - -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. - -;; Author: Daniel Mendler <mail@daniel-mendler.de> -;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> -;; Created: 2022 -;; Version: 0.1 -;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.0")) -;; Homepage: https://github.com/minad/corfu - -;; This file is part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; Show candidate documentation in echo area. Enable `corfu-echo-mode'. - -;;; Code: - -(require 'corfu) -(eval-when-compile - (require 'subr-x)) - -(defface corfu-echo - '((t :inherit completions-annotations)) - "Face used for echo area messages." - :group 'corfu-faces) - -(defcustom corfu-echo-delay '(2.0 . 1.0) - "Show documentation string in the echo area after that number of seconds. -The value can be a pair of two floats to specify initial and -subsequent delay." - :type '(choice (const :tag "Never" nil) - (number :tag "Delay in seconds") - (cons :tag "Two Delays" - (choice :tag "Initial " number) - (choice :tag "Subsequent" number))) - :group 'corfu) - -(defvar-local corfu-echo--timer nil - "Echo area message timer.") - -(defvar-local corfu-echo--message nil - "Last echo message.") - -(defun corfu-echo--cancel (&optional msg) - "Cancel echo timer and refresh MSG." - (when corfu-echo--timer - (cancel-timer corfu-echo--timer) - (setq corfu-echo--timer nil)) - (corfu-echo--show msg) - (unless corfu-echo--message - (kill-local-variable 'corfu-echo--timer) - (kill-local-variable 'corfu-echo--message))) - -(defun corfu-echo--show (msg) - "Show MSG in echo area." - (when (or msg corfu-echo--message) - (setq msg (or msg "") - corfu-echo--message msg) - (corfu--message "%s" (if (text-property-not-all 0 (length msg) 'face nil msg) - msg - (propertize msg 'face 'corfu-echo))))) - -;;;###autoload -(define-minor-mode corfu-echo-mode - "Show candidate documentation in echo area." - :global t :group 'corfu) - -(cl-defmethod corfu--exhibit :after (&context (corfu-echo-mode (eql t)) &optional _auto) - (if-let ((delay (if (consp corfu-echo-delay) - (funcall (if corfu-echo--message #'cdr #'car) - corfu-echo-delay) - corfu-echo-delay)) - (fun (plist-get corfu--extra :company-docsig)) - (cand (and (>= corfu--index 0) - (nth corfu--index corfu--candidates)))) - (if (<= delay 0) - (corfu-echo--show (funcall fun cand)) - (corfu-echo--cancel) - (setq corfu-echo--timer - (run-at-time delay nil - (lambda () - (corfu-echo--show (funcall fun cand)))))) - (corfu-echo--cancel))) - -(cl-defmethod corfu--teardown :before (&context (corfu-echo-mode (eql t))) - (corfu-echo--cancel)) - -(cl-defmethod corfu--prepare :before (&context (corfu-echo-mode (eql t))) - ;; The refreshing is needed to prevent flicker if corfu-echo-delay=t. - (corfu-echo--cancel corfu-echo--message)) - -(provide 'corfu-echo) -;;; corfu-echo.el ends here diff --git a/elpa/corfu-1.0/corfu-history.el b/elpa/corfu-1.0/corfu-history.el @@ -1,92 +0,0 @@ -;;; corfu-history.el --- Sorting by history for Corfu -*- lexical-binding: t -*- - -;; Copyright (C) 2022-2023 Free Software Foundation, Inc. - -;; Author: Daniel Mendler <mail@daniel-mendler.de> -;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> -;; Created: 2022 -;; Version: 0.1 -;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.0")) -;; Homepage: https://github.com/minad/corfu - -;; This file is part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; Enable `corfu-history-mode' to sort candidates by their history -;; position. Maintain a list of recently selected candidates. In order -;; to save the history across Emacs sessions, enable `savehist-mode' and -;; add `corfu-history' to `savehist-additional-variables'. -;; -;; (corfu-history-mode 1) -;; (savehist-mode 1) -;; (add-to-list 'savehist-additional-variables 'corfu-history) - -;;; Code: - -(require 'corfu) -(eval-when-compile - (require 'cl-lib)) - -(defvar corfu-history nil - "History of Corfu candidates. -The maximum length is determined by the variable `history-length' -or the property `history-length' of `corfu-history'.") - -(defvar corfu-history--hash nil - "Hash table of Corfu candidates.") - -(defun corfu-history--sort-predicate (x y) - "Sorting predicate which compares X and Y." - (or (< (cdr x) (cdr y)) - (and (= (cdr x) (cdr y)) - (corfu--length-string< (car x) (car y))))) - -(defun corfu-history--sort (candidates) - "Sort CANDIDATES by history." - (unless corfu-history--hash - (setq corfu-history--hash (make-hash-table :test #'equal :size (length corfu-history))) - (cl-loop for elem in corfu-history for index from 0 do - (unless (gethash elem corfu-history--hash) - (puthash elem index corfu-history--hash)))) - ;; Decorate each candidate with (index<<13) + length. This way we sort first by index and then by - ;; length. We assume that the candidates are shorter than 2**13 characters and that the history is - ;; shorter than 2**16 entries. - (cl-loop for cand on candidates do - (setcar cand (cons (car cand) - (+ (ash (gethash (car cand) corfu-history--hash #xFFFF) 13) - (length (car cand)))))) - (setq candidates (sort candidates #'corfu-history--sort-predicate)) - (cl-loop for cand on candidates do (setcar cand (caar cand))) - candidates) - -;;;###autoload -(define-minor-mode corfu-history-mode - "Update Corfu history and sort completions by history." - :global t :group 'corfu - (if corfu-history-mode - (add-function :override corfu-sort-function #'corfu-history--sort) - (remove-function corfu-sort-function #'corfu-history--sort))) - -(cl-defmethod corfu--insert :before (_status &context (corfu-history-mode (eql t))) - (when (>= corfu--index 0) - (add-to-history 'corfu-history - (substring-no-properties - (nth corfu--index corfu--candidates))) - (setq corfu-history--hash nil))) - -(provide 'corfu-history) -;;; corfu-history.el ends here diff --git a/elpa/corfu-1.0/corfu-indexed.el b/elpa/corfu-1.0/corfu-indexed.el @@ -1,97 +0,0 @@ -;;; corfu-indexed.el --- Select indexed candidates -*- lexical-binding: t -*- - -;; Copyright (C) 2022-2023 Free Software Foundation, Inc. - -;; Author: Luis Henriquez-Perez <luis@luishp.xyz>, Daniel Mendler <mail@daniel-mendler.de> -;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> -;; Created: 2022 -;; Version: 0.1 -;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.0")) -;; Homepage: https://github.com/minad/corfu - -;; This file is part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; This package is a Corfu extension, which prefixes candidates with indices if -;; enabled via `corfu-indexed-mode'. It allows you to select candidates with -;; prefix arguments. This is designed to be a faster alternative to selecting a -;; candidate with `corfu-next' and `corfu-previous'. - -;;; Code: - -(require 'corfu) -(eval-when-compile - (require 'cl-lib)) - -(defface corfu-indexed - '((default :height 0.75) - (((class color) (min-colors 88) (background dark)) - :foreground "#f4f4f4" :background "#323232") - (((class color) (min-colors 88) (background light)) - :foreground "#404148" :background "#d7d7d7") - (t :background "black")) - "Face used for the candidate index prefix." - :group 'corfu-faces) - -(defcustom corfu-indexed-start 0 - "Start of the indexing." - :group 'corfu - :type 'natnum) - -(defvar corfu-indexed--commands - '(corfu-insert corfu-complete) - "Commands that should be indexed.") - -;;;###autoload -(define-minor-mode corfu-indexed-mode - "Prefix candidates with indices." - :global t :group 'corfu) - -(cl-defmethod corfu--prepare :before (&context (corfu-indexed-mode (eql t))) - (when (and prefix-arg (memq this-command corfu-indexed--commands)) - (let ((index (+ corfu--scroll - (- (prefix-numeric-value prefix-arg) - corfu-indexed-start)))) - (if (and (>= index 0) - (< index corfu--total) - (< index (+ corfu--scroll corfu-count))) - (setq corfu--index index) - (message "Out of range") - (setq this-command #'ignore))))) - -(cl-defmethod corfu--affixate :around (cands &context (corfu-indexed-mode (eql t))) - (setq cands (cdr (cl-call-next-method cands))) - (let* ((space #(" " 0 1 (face (:height 0.5 :inherit corfu-indexed)))) - (width (if (length> cands (- 10 corfu-indexed-start)) 2 1)) - (fmt (concat space - (propertize (format "%%%ds" width) - 'face 'corfu-indexed) - space)) - (align - (propertize (make-string width ?\s) - 'display - `(space :align-to (+ left ,(1+ width)))))) - (cl-loop for cand in cands for index from corfu-indexed-start do - (setf (cadr cand) - (concat - (propertize " " 'display (format fmt index)) - align - (cadr cand)))) - (cons t cands))) - -(provide 'corfu-indexed) -;;; corfu-indexed.el ends here diff --git a/elpa/corfu-1.0/corfu-info.el b/elpa/corfu-1.0/corfu-info.el @@ -1,116 +0,0 @@ -;;; corfu-info.el --- Show candidate information in separate buffer -*- lexical-binding: t -*- - -;; Copyright (C) 2022-2023 Free Software Foundation, Inc. - -;; Author: Daniel Mendler <mail@daniel-mendler.de> -;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> -;; Created: 2022 -;; Version: 0.1 -;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.0")) -;; Homepage: https://github.com/minad/corfu - -;; This file is part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; This Corfu extension provides commands to show additional information to the -;; candidates in a separate buffer. The commands `corfu-info-location' and -;; `corfu-info-documentation' are bound by default in the `corfu-map' to M-g and -;; M-h respectively. - -;;; Code: - -(require 'corfu) -(eval-when-compile - (require 'subr-x)) - -(defun corfu-info--restore-on-next-command () - "Restore window configuration before next command." - (let ((config (current-window-configuration)) - (other other-window-scroll-buffer) - (restore (make-symbol "corfu--restore"))) - (fset restore - (lambda () - (setq other-window-scroll-buffer other) - (unless (memq this-command '(scroll-other-window scroll-other-window-down)) - (when (memq this-command '(corfu-quit corfu-reset)) - (setq this-command #'ignore)) - (remove-hook 'pre-command-hook restore) - (set-window-configuration config)))) - (add-hook 'pre-command-hook restore))) - -(defun corfu-info--display-buffer (buffer name) - "Display BUFFER and return window displaying the buffer. -Make the buffer persistent with NAME if non-nil." - (if name - (unless (buffer-local-value 'buffer-file-name buffer) - (if-let ((old (get-buffer name))) - (setq buffer (prog1 old (kill-buffer buffer))) - (with-current-buffer buffer - (rename-buffer name)))) - (corfu-info--restore-on-next-command)) - (setq other-window-scroll-buffer buffer) - (display-buffer buffer t)) - -;;;###autoload -(defun corfu-info-documentation (&optional arg) - "Show documentation of current candidate. -If called with a prefix ARG, the buffer is persistent." - (interactive "P") - ;; Company support, taken from `company.el', see `company-show-doc-buffer'. - (when (< corfu--index 0) - (user-error "No candidate selected")) - (let ((cand (nth corfu--index corfu--candidates))) - (if-let ((fun (plist-get corfu--extra :company-doc-buffer)) - (res (funcall fun cand))) - (set-window-start (corfu-info--display-buffer - (get-buffer (or (car-safe res) res)) - (and arg (format "*corfu doc: %s*" cand))) - (or (cdr-safe res) (point-min))) - (user-error "No documentation available for `%s'" cand)))) - -;;;###autoload -(defun corfu-info-location (&optional arg) - "Show location of current candidate. -If called with a prefix ARG, the buffer is persistent." - (interactive "P") - ;; Company support, taken from `company.el', see `company-show-location'. - (when (< corfu--index 0) - (user-error "No candidate selected")) - (let ((cand (nth corfu--index corfu--candidates))) - ;; BUG: company-location may throw errors if location is not found - (if-let ((fun (ignore-errors (plist-get corfu--extra :company-location))) - (loc (funcall fun cand))) - (with-selected-window - (corfu-info--display-buffer - (or (and (bufferp (car loc)) (car loc)) - (find-file-noselect (car loc) t)) - (and arg (format "*corfu loc: %s*" cand))) - (without-restriction - (goto-char (point-min)) - (when-let ((pos (cdr loc))) - (if (bufferp (car loc)) - (goto-char pos) - (forward-line (1- pos)))) - (set-window-start nil (point)))) - (user-error "No location available for `%s'" cand)))) - -;; Emacs 28: Do not show Corfu commands with M-X -(put #'corfu-info-location 'completion-predicate #'ignore) -(put #'corfu-info-documentation 'completion-predicate #'ignore) - -(provide 'corfu-info) -;;; corfu-info.el ends here diff --git a/elpa/corfu-1.0/corfu-pkg.el b/elpa/corfu-1.0/corfu-pkg.el @@ -1,2 +0,0 @@ -;; Generated package description from corfu.el -*- no-byte-compile: t -*- -(define-package "corfu" "1.0" "COmpletion in Region FUnction" '((emacs "27.1") (compat "29.1.4.4")) :commit "24dccafeea114b1aec7118f2a8405b46aa0051e0" :authors '(("Daniel Mendler" . "mail@daniel-mendler.de")) :maintainer '("Daniel Mendler" . "mail@daniel-mendler.de") :keywords '("abbrev" "convenience" "matching" "completion" "wp") :url "https://github.com/minad/corfu") diff --git a/elpa/corfu-1.0/corfu-popupinfo.el b/elpa/corfu-1.0/corfu-popupinfo.el @@ -1,522 +0,0 @@ -;;; corfu-popupinfo.el --- Candidate information popup for Corfu -*- lexical-binding: t -*- - -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. - -;; Author: Yuwei Tian <fishtai0@gmail.com>, Daniel Mendler <mail@daniel-mendler.de> -;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> -;; Created: 2022 -;; Version: 0.1 -;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.0")) -;; Homepage: https://github.com/minad/corfu - -;; This file is part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; Display an information popup for completion candidate when using -;; Corfu. The popup displays either the candidate documentation or the -;; candidate location. The `corfu-popupinfo-mode' must be enabled -;; globally. Set `corfu-popupinfo-delay' to nil if the info popup should -;; not update automatically. If the popup should not appear initially, -;; but update automatically afterwards, use `(setq corfu-popupinfo-delay -;; (cons nil 1.0))'. - -;; For manual toggling the commands `corfu-popupinfo-toggle', -;; `corfu-popupinfo-location' and `corfu-popupinfo-documentation' are -;; bound in the `corfu-popupinfo-map'. - -;;; Code: - -(require 'corfu) -(eval-when-compile - (require 'cl-lib) - (require 'subr-x)) - -(defface corfu-popupinfo - '((t :inherit corfu-default)) - "Face used for the info popup." - :group 'corfu-faces) - -(defcustom corfu-popupinfo-delay '(2.0 . 1.0) - "Automatically update info popup after that number of seconds. - -The value can be a pair of two floats to specify initial and -subsequent delay. If the value is non-nil or the car of the pair -is non-nil, the popup will automatically appear for the -preselected candidate. Otherwise the popup can be requested -manually via `corfu-popupinfo-toggle', -`corfu-popupinfo-documentation' and `corfu-popupinfo-location'. - -It is *not recommended* to use a short delay or even 0, since -this will create high load for Emacs. Retrieving the -documentation from the backend is usually expensive." - :type '(choice (const :tag "Never" nil) - (number :tag "Delay in seconds") - (cons :tag "Two Delays" - (choice :tag "Initial " - (choice (const nil) number)) - (choice :tag "Subsequent" - (choice (const nil) number)))) - :group 'corfu) - -(defcustom corfu-popupinfo-hide t - "Hide the popup during the transition between candidates." - :type 'boolean - :group 'corfu) - -(defcustom corfu-popupinfo-max-width 80 - "The maximum width of the info popup in characters." - :type 'natnum - :group 'corfu) - -(defcustom corfu-popupinfo-min-width 30 - "The minimum width of the info popup in characters." - :type 'natnum - :group 'corfu) - -(defcustom corfu-popupinfo-max-height 10 - "The maximum height of the info popup in characters." - :type 'natnum - :group 'corfu) - -(defcustom corfu-popupinfo-min-height 1 - "The minimum height of the info popup in characters." - :type 'natnum - :group 'corfu) - -(defcustom corfu-popupinfo-resize t - "Resize the info popup automatically if non-nil." - :type 'boolean - :group 'corfu) - -(defcustom corfu-popupinfo-direction '(right left vertical) - "Preferred directions for the popup in order." - :type '(repeat - (choice - (const left) - (const right) - (const vertical) - (const force-left) - (const force-right) - (const force-horizontal) - (const force-vertical))) - :group 'corfu) - -(defvar-keymap corfu-popupinfo-map - :doc "Additional keymap activated in popupinfo mode." - "M-t" #'corfu-popupinfo-toggle - "<remap> <corfu-info-documentation>" #'corfu-popupinfo-documentation - "<remap> <corfu-info-location>" #'corfu-popupinfo-location - "<remap> <scroll-other-window>" #'corfu-popupinfo-scroll-up - "<remap> <scroll-other-window-down>" #'corfu-popupinfo-scroll-down - "<remap> <end-of-buffer-other-window>" #'corfu-popupinfo-end - "<remap> <beginning-of-buffer-other-window>" #'corfu-popupinfo-beginning) - -(defvar corfu-popupinfo--buffer-parameters - '((truncate-partial-width-windows . nil) - (truncate-lines . nil) - (left-margin-width . 1) - (right-margin-width . 1) - (word-wrap . t) - (fringe-indicator-alist (continuation))) - "Buffer parameters.") - -(defvar-local corfu-popupinfo--toggle 'init - "Local toggle state.") - -(defvar-local corfu-popupinfo--function - #'corfu-popupinfo--get-documentation - "Function called to obtain documentation string.") - -(defvar corfu-popupinfo--frame nil - "Info popup child frame.") - -(defvar corfu-popupinfo--timer nil - "Corfu info popup auto display timer.") - -(defvar-local corfu-popupinfo--candidate nil - "Completion candidate for the info popup.") - -(defvar-local corfu-popupinfo--coordinates nil - "Coordinates of the candidate popup. -The coordinates list has the form (LEFT TOP RIGHT BOTTOM) where -all values are in pixels relative to the origin. See -`frame-edges' for details.") - -(defvar-local corfu-popupinfo--lock-dir nil - "Locked position direction of the info popup.") - -(defconst corfu-popupinfo--state-vars - '(corfu-popupinfo--candidate - corfu-popupinfo--coordinates - corfu-popupinfo--lock-dir - corfu-popupinfo--toggle - corfu-popupinfo--function) - "Buffer-local state variables used by corfu-popupinfo.") - -(defun corfu-popupinfo--visible-p (&optional frame) - "Return non-nil if FRAME is visible." - (setq frame (or frame corfu-popupinfo--frame)) - (and (frame-live-p frame) (frame-visible-p frame))) - -(defun corfu-popupinfo--get-location (candidate) - "Get source at location of CANDIDATE." - (save-excursion - (let ((old-buffers (buffer-list)) (buffer nil)) - (unwind-protect - (when-let - ((fun (plist-get corfu--extra :company-location)) - ;; BUG: company-location may throw errors if location is not found - (loc (ignore-errors (funcall fun candidate))) - ((setq buffer - (or (and (bufferp (car loc)) (car loc)) - (get-file-buffer (car loc)) - (let ((inhibit-message t) - (message-log-max nil) - (inhibit-redisplay t) - (enable-dir-local-variables nil) - (enable-local-variables :safe) - (non-essential t) - (delay-mode-hooks t) - (find-file-hook '(global-font-lock-mode-check-buffers))) - (find-file-noselect (car loc) t)))))) - (with-current-buffer buffer - (save-excursion - (without-restriction - (goto-char (point-min)) - (when-let ((pos (cdr loc))) - (if (bufferp (car loc)) - (goto-char pos) - (forward-line (1- pos)))) - (let ((beg (point))) - ;; Support a little bit of scrolling. - (forward-line (* 10 corfu-popupinfo-max-height)) - (when jit-lock-mode - (jit-lock-fontify-now beg (point))) - (let ((res (buffer-substring beg (point)))) - (and (not (string-blank-p res)) res))))))) - (when (and buffer (not (memq buffer old-buffers))) - (kill-buffer buffer)))))) - -(defun corfu-popupinfo--get-documentation (candidate) - "Get the documentation for CANDIDATE." - (when-let ((fun (plist-get corfu--extra :company-doc-buffer)) - (res (save-excursion - (let ((inhibit-message t) - (message-log-max nil) - (inhibit-redisplay t) - ;; Reduce print length for elisp backend (#249) - (print-level 3) - (print-length (* corfu-popupinfo-max-width - corfu-popupinfo-max-height))) - (funcall fun candidate))))) - (with-current-buffer (or (car-safe res) res) - (setq res (string-trim - (replace-regexp-in-string - "[\n\t ]*\\[back\\][\n\t ]*" "" - (buffer-string)))) - (and (not (string-blank-p res)) res)))) - -(defun corfu-popupinfo--size () - "Return popup size as pair." - (let* ((cw (default-font-width)) - (lh (default-line-height)) - (margin - (* cw (+ (alist-get 'left-margin-width corfu-popupinfo--buffer-parameters) - (alist-get 'right-margin-width corfu-popupinfo--buffer-parameters)))) - (max-height (* lh corfu-popupinfo-max-height)) - (max-width (* cw corfu-popupinfo-max-width))) - (or (when corfu-popupinfo-resize - (with-current-buffer " *corfu-popupinfo*" - (cl-letf* (((window-dedicated-p) nil) - ((window-buffer) (current-buffer)) - (size (window-text-pixel-size - nil (point-min) (point-max) - ;; Use 3*max-height as y-limit, to take more text - ;; into account. - max-width (* 3 max-height)))) - ;; Check that width is not exceeded. Otherwise use full height, - ;; since lines will get wrapped. - (when (<= (car size) max-width) - (cons (+ margin (car size)) - ;; XXX HACK: Ensure that popup has at least a height of 1, - ;; which is the minimum frame height (#261). Maybe we - ;; should ask upstream how smaller frames can be created. - ;; I only managed to create smaller frames by setting - ;; `window-safe-min-height' to 0, which feels problematic. - (min (max (cdr size) lh) max-height)))))) - (cons (+ margin max-width) max-height)))) - -(defun corfu-popupinfo--frame-geometry (frame) - "Return position and size geometric attributes of FRAME. - -The geometry represents the position and size in pixels -in the form of (X Y WIDTH HEIGHT)." - (pcase-let ((`(,x . ,y) (frame-position frame))) - (list x y (frame-pixel-width frame) (frame-pixel-height frame)))) - -(defun corfu-popupinfo--fits-p (size area) - "Check if SIZE fits into the AREA. - -SIZE is in the form (WIDTH . HEIGHT). -AREA is in the form (X Y WIDTH HEIGHT DIR)." - (and (>= (nth 2 area) (car size)) (>= (nth 3 area) (cdr size)))) - -(defun corfu-popupinfo--larger-p (area1 area2) - "Check if AREA1 is larger than AREA2. - -AREA1 and AREA2 are both in the form (X Y WIDTH HEIGHT DIR)." - (>= (* (nth 2 area1) (nth 3 area1)) (* (nth 2 area2) (nth 3 area2)))) - -(defun corfu-popupinfo--area (ps) - "Calculate the display area for the info popup. - -PS is the pixel size of the popup. The calculated area is in the -form (X Y WIDTH HEIGHT DIR)." - (pcase-let* - ((cw (default-font-width)) - (lh (default-line-height)) - (border (alist-get 'child-frame-border-width corfu--frame-parameters)) - (`(,_pfx ,_pfy ,pfw ,pfh) - (corfu-popupinfo--frame-geometry (frame-parent corfu--frame))) - (`(,cfx ,cfy ,cfw ,cfh) (corfu-popupinfo--frame-geometry corfu--frame)) - ;; Candidates popup below input - (below (>= cfy (+ lh (cadr (window-inside-pixel-edges)) - (window-tab-line-height) - (or (cdr (posn-x-y (posn-at-point (point)))) 0)))) - ;; Popups aligned at top - (top-aligned (or below (< (cdr ps) cfh))) - ;; Left display area - (ahy (if top-aligned - cfy - (max 0 (- (+ cfy cfh) border border (cdr ps))))) - (ahh (if top-aligned - (min (- pfh cfy) (cdr ps)) - (min (- (+ cfy cfh) border border) (cdr ps)))) - (al (list (max 0 (- cfx (car ps) border)) ahy - (min (- cfx border) (car ps)) ahh 'left)) - ;; Right display area - (arx (+ cfx cfw (- border))) - (ar (list arx ahy (min (- pfw arx border border) (car ps)) ahh 'right)) - ;; Vertical display area - (avw (min (car ps) (- pfw cfx border border))) - (av (if below - (list cfx (+ cfy cfh (- border)) avw (min (- pfh cfy cfh border) (cdr ps)) 'vertical) - (let ((h (min (- cfy border border) (cdr ps)))) - (list cfx (max 0 (- cfy h border)) avw h 'vertical))))) - (unless (and corfu-popupinfo--lock-dir - (corfu-popupinfo--fits-p - (cons (* cw corfu-popupinfo-min-width) (* lh corfu-popupinfo-min-height)) - (pcase corfu-popupinfo--lock-dir ('left al) ('right ar) ('vertical av)))) - (setq corfu-popupinfo--lock-dir nil)) - (or - (cl-loop for dir in corfu-popupinfo-direction thereis - (pcase dir - ((or 'force-right (guard (eq corfu-popupinfo--lock-dir 'right))) ar) - ((or 'force-left (guard (eq corfu-popupinfo--lock-dir 'left))) al) - ((or 'force-vertical (guard (eq corfu-popupinfo--lock-dir 'vertical))) av) - ((and 'right (guard (corfu-popupinfo--fits-p ps ar))) ar) - ((and 'left (guard (corfu-popupinfo--fits-p ps al))) al) - ((and 'vertical (guard (corfu-popupinfo--fits-p ps av))) av))) - (let ((ah (if (corfu-popupinfo--larger-p ar al) ar al))) - (if (corfu-popupinfo--larger-p av ah) av ah))))) - -(defun corfu-popupinfo--show (candidate) - "Show the info popup for CANDIDATE." - (when corfu-popupinfo--timer - (cancel-timer corfu-popupinfo--timer) - (setq corfu-popupinfo--timer nil)) - (when (and (corfu-popupinfo--visible-p corfu--frame)) - (let* ((cand-changed - (not (and (corfu-popupinfo--visible-p) - (equal candidate corfu-popupinfo--candidate)))) - (new-coords (frame-edges corfu--frame 'inner-edges)) - (coords-changed (not (equal new-coords corfu-popupinfo--coordinates)))) - (when cand-changed - (if-let ((content (funcall corfu-popupinfo--function candidate))) - (with-current-buffer (corfu--make-buffer " *corfu-popupinfo*") - (with-silent-modifications - (erase-buffer) - (insert content) - (goto-char (point-min))) - (dolist (var corfu-popupinfo--buffer-parameters) - (set (make-local-variable (car var)) (cdr var))) - (when-let ((m (memq 'corfu-default (alist-get 'default face-remapping-alist)))) - (setcar m 'corfu-popupinfo))) - (corfu-popupinfo--hide) - (setq cand-changed nil coords-changed nil))) - (when (or cand-changed coords-changed) - (pcase-let* ((border (alist-get 'child-frame-border-width corfu--frame-parameters)) - (`(,area-x ,area-y ,area-w ,area-h ,area-d) - (corfu-popupinfo--area - (if cand-changed - (corfu-popupinfo--size) - (cons - (- (frame-pixel-width corfu-popupinfo--frame) border border) - (- (frame-pixel-height corfu-popupinfo--frame) border border))))) - (margin-quirk (not corfu-popupinfo--frame))) - (setq corfu-popupinfo--frame - (corfu--make-frame corfu-popupinfo--frame - area-x area-y area-w area-h - " *corfu-popupinfo*") - corfu-popupinfo--toggle t - corfu-popupinfo--lock-dir area-d - corfu-popupinfo--candidate candidate - corfu-popupinfo--coordinates new-coords) - ;; XXX HACK: Force margin update. For some reason, the call to - ;; `set-window-buffer' in `corfu--make-frame' is not effective the - ;; first time. Why does Emacs have all these quirks? - (when margin-quirk - (set-window-buffer - (frame-root-window corfu-popupinfo--frame) - " *corfu-popupinfo*"))))))) - -(defun corfu-popupinfo--hide () - "Clear the info popup buffer content and hide it." - (corfu--hide-frame corfu-popupinfo--frame)) - -(defun corfu-popupinfo-end (&optional n) - "Scroll text of info popup window to its end. - -If arg N is omitted or nil, scroll to end. If a numerical value, -put point N/10 of the way from the end. If the info popup is not -visible, the other window is moved to beginning or end." - (interactive "P") - (if (corfu-popupinfo--visible-p) - (with-selected-frame corfu-popupinfo--frame - (with-current-buffer " *corfu-popupinfo*" - (with-no-warnings - (end-of-buffer n)))) - (end-of-buffer-other-window n))) - -(defun corfu-popupinfo-beginning (&optional n) - "Scroll text of info popup window to beginning of buffer. - -See `corfu-popupinfo-end' for the argument N." - (interactive "P") - (corfu-popupinfo-end (- 10 (if (numberp n) n 0)))) - -(defun corfu-popupinfo-scroll-up (&optional n) - "Scroll text of info popup window upward N lines. - -If ARG is omitted or nil, scroll upward by a near full screen. -See `scroll-up' for details. If the info popup is not visible, -the other window is scrolled." - (interactive "p") - (if (corfu-popupinfo--visible-p) - (with-selected-frame corfu-popupinfo--frame - (with-current-buffer " *corfu-popupinfo*" - (scroll-up n))) - (scroll-other-window n))) - -(defun corfu-popupinfo-scroll-down (&optional n) - "Scroll text of info popup window down N lines. - -See `corfu-popupinfo-scroll-up' for more details." - (interactive "p") - (corfu-popupinfo-scroll-up (- (or n 1)))) - -(defun corfu-popupinfo--toggle (fun) - "Set documentation getter FUN and toggle popup." - (when (< corfu--index 0) - (corfu-popupinfo--hide) - (user-error "No candidate selected")) - (setq corfu-popupinfo--toggle - (not (and (corfu-popupinfo--visible-p) - (eq corfu-popupinfo--function fun)))) - (if (not corfu-popupinfo--toggle) - (corfu-popupinfo--hide) - (setq corfu-popupinfo--function fun - corfu-popupinfo--candidate nil) - (let ((cand (nth corfu--index corfu--candidates))) - (corfu-popupinfo--show cand) - (unless (corfu-popupinfo--visible-p) - (user-error "No %s available for `%s'" - (car (last (split-string (symbol-name fun) "-+"))) - cand))))) - -(defun corfu-popupinfo-documentation () - "Show or hide documentation in popup. -Behaves like `corfu-popupinfo-toggle'." - (interactive) - (corfu-popupinfo--toggle #'corfu-popupinfo--get-documentation)) - -(defun corfu-popupinfo-location () - "Show or hide location in popup. -Behaves like `corfu-popupinfo-toggle'." - (interactive) - (corfu-popupinfo--toggle #'corfu-popupinfo--get-location)) - -(defun corfu-popupinfo-toggle () - "Toggle the info popup display or hide. - -When using this command to manually hide the info popup, it will -not be displayed until this command is called again, even if -`corfu-popupinfo-delay' is non-nil." - (interactive) - (corfu-popupinfo--toggle corfu-popupinfo--function)) - -;;;###autoload -(define-minor-mode corfu-popupinfo-mode - "Corfu info popup minor mode." - :global t :group 'corfu) - -(cl-defmethod corfu--exhibit :after (&context (corfu-popupinfo-mode (eql t)) &optional _auto) - (when completion-in-region-mode - (setf (alist-get #'corfu-popupinfo-mode minor-mode-overriding-map-alist) - corfu-popupinfo-map) - (when corfu-popupinfo--timer - (cancel-timer corfu-popupinfo--timer) - (setq corfu-popupinfo--timer nil)) - (if (and (>= corfu--index 0) (corfu-popupinfo--visible-p corfu--frame)) - (let ((cand (nth corfu--index corfu--candidates))) - (if-let ((delay (if (consp corfu-popupinfo-delay) - (funcall (if (eq corfu-popupinfo--toggle 'init) #'car #'cdr) - corfu-popupinfo-delay) - corfu-popupinfo-delay)) - (corfu-popupinfo--toggle)) - (if (or (<= delay 0) - (and (equal cand corfu-popupinfo--candidate) - (corfu-popupinfo--visible-p))) - (corfu-popupinfo--show cand) - (when (corfu-popupinfo--visible-p) - (cond - (corfu-popupinfo-hide - (corfu-popupinfo--hide)) - (corfu-popupinfo--candidate - (corfu-popupinfo--show corfu-popupinfo--candidate)))) - (setq corfu-popupinfo--timer - (run-at-time delay nil #'corfu-popupinfo--show cand))) - (unless (equal cand corfu-popupinfo--candidate) - (corfu-popupinfo--hide)))) - (corfu-popupinfo--hide)))) - -(cl-defmethod corfu--teardown :before (&context (corfu-popupinfo-mode (eql t))) - (corfu-popupinfo--hide) - (mapc #'kill-local-variable corfu-popupinfo--state-vars) - (setq minor-mode-overriding-map-alist - (assq-delete-all #'corfu-popupinfo-mode - minor-mode-overriding-map-alist))) - -;; Emacs 28: Do not show Corfu commands with M-X -(dolist (sym '(corfu-popupinfo-scroll-down corfu-popupinfo-scroll-up - corfu-popupinfo-documentation corfu-popupinfo-location - corfu-popupinfo-beginning corfu-popupinfo-end - corfu-popupinfo-toggle)) - (put sym 'completion-predicate #'ignore)) - -(provide 'corfu-popupinfo) -;;; corfu-popupinfo.el ends here diff --git a/elpa/corfu-1.0/corfu-quick.el b/elpa/corfu-1.0/corfu-quick.el @@ -1,154 +0,0 @@ -;;; corfu-quick.el --- Quick keys for Corfu -*- lexical-binding: t -*- - -;; Copyright (C) 2022-2023 Free Software Foundation, Inc. - -;; Author: Luis Henriquez-Perez <luis@luishp.xyz>, Daniel Mendler <mail@daniel-mendler.de> -;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> -;; Created: 2022 -;; Version: 0.1 -;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.0")) -;; Homepage: https://github.com/minad/corfu - -;; This file is part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; This package is a Corfu extension, which prefixes candidates with -;; quick keys. Typing these quick keys allows you to select the -;; candidate in front of them. This is designed to be a faster -;; alternative to selecting a candidate with `corfu-next' and -;; `corfu-previous'. -;; (keymap-set corfu-map "M-q" #'corfu-quick-complete) -;; (keymap-set corfu-map "C-q" #'corfu-quick-insert) - -;;; Code: - -(require 'corfu) -(eval-when-compile - (require 'cl-lib)) - -(defcustom corfu-quick1 "asdfgh" - "First level quick keys." - :type 'string - :group 'corfu) - -(defcustom corfu-quick2 "jkluionm" - "Second level quick keys." - :type 'string - :group 'corfu) - -(defface corfu-quick1 - '((((class color) (min-colors 88) (background dark)) - :background "#0050af" :foreground "white" :inherit bold) - (((class color) (min-colors 88) (background light)) - :background "#7feaff" :foreground "black" :inherit bold) - (t :background "blue" :foreground "white" :inherit bold)) - "Face used for the first quick key." - :group 'corfu-faces) - -(defface corfu-quick2 - '((((class color) (min-colors 88) (background dark)) - :background "#7f1f7f" :foreground "white" :inherit bold) - (((class color) (min-colors 88) (background light)) - :background "#ffaaff" :foreground "black" :inherit bold) - (t :background "magenta" :foreground "white" :inherit bold)) - "Face used for the second quick key." - :group 'corfu-faces) - -(defun corfu-quick--keys (two idx) ;; See vertico-quick--keys - "Format quick keys prefix. -IDX is the current candidate index. -TWO is non-nil if two keys should be displayed." - (let ((fst (length corfu-quick1)) - (snd (length corfu-quick2))) - (if (>= idx fst) - (let ((first (elt corfu-quick2 (mod (/ (- idx fst) fst) snd))) - (second (elt corfu-quick1 (mod (- idx fst) fst)))) - (cond - ((eq first two) - (list - (concat " " (propertize (char-to-string second) 'face 'corfu-quick1)) - (cons second (+ corfu--scroll idx)))) - (two - (list " ")) - (t - (list - (concat (propertize (char-to-string first) 'face 'corfu-quick1) - (propertize (char-to-string second) 'face 'corfu-quick2)) - (cons first (list first)))))) - (let ((first (elt corfu-quick1 (mod idx fst)))) - (if two - (list " ") - (list - (concat (propertize (char-to-string first) 'face 'corfu-quick1) " ") - (cons first (+ corfu--scroll idx)))))))) - -(defun corfu-quick--read (&optional first) - "Read quick key given FIRST pressed key." - (cl-letf* ((list nil) - (space1 (propertize " " 'display - `(space :width - (+ 0.5 (,(alist-get - 'child-frame-border-width - corfu--frame-parameters)))))) - (space2 #(" " 0 1 (display (space :width 0.5)))) - (orig (symbol-function #'corfu--affixate)) - ((symbol-function #'corfu--affixate) - (lambda (cands) - (setq cands (cdr (funcall orig cands))) - (cl-loop for cand in cands for index from 0 do - (pcase-let ((`(,keys . ,events) (corfu-quick--keys first index))) - (setq list (nconc events list)) - (setf (cadr cand) (concat space1 (propertize " " 'display keys) space2)))) - (cons t cands))) - ;; Increase minimum width to avoid odd jumping - (corfu-min-width (+ 3 corfu-min-width))) - (corfu--candidates-popup - (posn-at-point (+ (car completion-in-region--data) (length corfu--base)))) - (alist-get (read-key) list))) - -;;;###autoload -(defun corfu-quick-jump () - "Jump to candidate using quick keys." - (interactive) - (when (fboundp 'corfu-echo--cancel) - (corfu-echo--cancel)) - (if (= corfu--total 0) - (and (message "No match") nil) - (let ((idx (corfu-quick--read))) - (when (consp idx) (setq idx (corfu-quick--read (car idx)))) - (when idx (setq corfu--index idx))))) - -;;;###autoload -(defun corfu-quick-insert () - "Insert candidate using quick keys." - (interactive) - (when (corfu-quick-jump) - (corfu-insert))) - -;;;###autoload -(defun corfu-quick-complete () - "Complete candidate using quick keys." - (interactive) - (when (corfu-quick-jump) - (corfu-complete))) - -;; Emacs 28: Do not show Corfu commands in M-X -(dolist (sym '(corfu-quick-jump corfu-quick-insert corfu-quick-complete)) - (put sym 'completion-predicate #'ignore)) - -(provide 'corfu-quick) -;;; corfu-quick.el ends here diff --git a/elpa/corfu-1.0/corfu.el b/elpa/corfu-1.0/corfu.el @@ -1,1323 +0,0 @@ -;;; corfu.el --- COmpletion in Region FUnction -*- lexical-binding: t -*- - -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. - -;; Author: Daniel Mendler <mail@daniel-mendler.de> -;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> -;; Created: 2021 -;; Version: 1.0 -;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4")) -;; Homepage: https://github.com/minad/corfu -;; Keywords: abbrev, convenience, matching, completion, wp - -;; This file is part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; Corfu enhances in-buffer completion with a small completion popup. -;; The current candidates are shown in a popup below or above the -;; point. The candidates can be selected by moving up and down. -;; Corfu is the minimalistic in-buffer completion counterpart of the -;; Vertico minibuffer UI. - -;;; Code: - -(require 'compat) -(eval-when-compile - (require 'cl-lib) - (require 'subr-x)) - -(defgroup corfu nil - "COmpletion in Region FUnction." - :link '(info-link :tag "Info Manual" "(corfu)") - :link '(url-link :tag "Homepage" "https://github.com/minad/corfu") - :link '(emacs-library-link :tag "Library Source" "corfu.el") - :group 'convenience - :group 'tools - :group 'matching - :prefix "corfu-") - -(defcustom corfu-count 10 - "Maximal number of candidates to show." - :type 'natnum) - -(defcustom corfu-scroll-margin 2 - "Number of lines at the top and bottom when scrolling. -The value should lie between 0 and corfu-count/2." - :type 'natnum) - -(defcustom corfu-min-width 15 - "Popup minimum width in characters." - :type 'natnum) - -(defcustom corfu-max-width 100 - "Popup maximum width in characters." - :type 'natnum) - -(defcustom corfu-cycle nil - "Enable cycling for `corfu-next' and `corfu-previous'." - :type 'boolean) - -(defcustom corfu-on-exact-match 'insert - "Configure how a single exact match should be handled." - :type '(choice (const insert) (const quit) (const nil))) - -(defcustom corfu-continue-commands - ;; nil is undefined command - '(nil ignore universal-argument universal-argument-more digit-argument - "\\`corfu-" "\\`scroll-other-window") - "Continue Corfu completion after executing these commands." - :type '(repeat (choice regexp symbol))) - -(defcustom corfu-preview-current 'insert - "Preview currently selected candidate. -If the variable has the value `insert', the candidate is automatically -inserted on further input." - :type '(choice boolean (const insert))) - -(defcustom corfu-preselect 'valid - "Configure if the prompt or first candidate is preselected. -- prompt: Always select the prompt. -- first: Always select the first candidate. -- valid: Only select the prompt if valid and not equal to the first candidate. -- directory: Like first, but select the prompt if it is a directory." - :type '(choice (const prompt) (const valid) (const first) (const directory))) - -(defcustom corfu-separator ?\s - "Component separator character. -The character used for separating components in the input. The presence -of this separator character will inhibit quitting at completion -boundaries, so that any further characters can be entered. To enter the -first separator character, call `corfu-insert-separator' (bound to M-SPC -by default). Useful for multi-component completion styles such as -Orderless." - :type 'character) - -(defcustom corfu-quit-at-boundary 'separator - "Automatically quit at completion boundary. -nil: Never quit at completion boundary. -t: Always quit at completion boundary. -separator: Quit at boundary if no `corfu-separator' has been inserted." - :type '(choice boolean (const separator))) - -(defcustom corfu-quit-no-match 'separator - "Automatically quit if no matching candidate is found. -When staying alive even if there is no match a warning message is -shown in the popup. -nil: Stay alive even if there is no match. -t: Quit if there is no match. -separator: Only stay alive if there is no match and -`corfu-separator' has been inserted." - :type '(choice boolean (const separator))) - -(defcustom corfu-left-margin-width 0.5 - "Width of the left margin in units of the character width." - :type 'float) - -(defcustom corfu-right-margin-width 0.5 - "Width of the right margin in units of the character width." - :type 'float) - -(defcustom corfu-bar-width 0.2 - "Width of the bar in units of the character width." - :type 'float) - -(defcustom corfu-margin-formatters nil - "Registry for margin formatter functions. -Each function of the list is called with the completion metadata as -argument until an appropriate formatter is found. The function should -return a formatter function, which takes the candidate string and must -return a string, possibly an icon." - :type 'hook) - -(defcustom corfu-sort-function #'corfu-sort-length-alpha - "Default sorting function, used if no `display-sort-function' is specified." - :type `(choice - (const :tag "No sorting" nil) - (const :tag "By length and alpha" ,#'corfu-sort-length-alpha) - (function :tag "Custom function"))) - -(defcustom corfu-sort-override-function nil - "Override sort function which overrides the `display-sort-function'." - :type '(choice (const nil) function)) - -(defcustom corfu-auto-prefix 3 - "Minimum length of prefix for auto completion. -The completion backend can override this with -:company-prefix-length. It is *not recommended* to use a small -prefix length (below 2), since this will create high load for -Emacs. See also `corfu-auto-delay'." - :type 'natnum) - -(defcustom corfu-auto-delay 0.2 - "Delay for auto completion. -It is *not recommended* to use a short delay or even 0, since -this will create high load for Emacs, in particular if executing -the completion backend is costly." - :type 'float) - -(defcustom corfu-auto-commands - '("self-insert-command\\'" - c-electric-colon c-electric-lt-gt c-electric-slash c-scope-operator) - "Commands which initiate auto completion." - :type '(repeat (choice regexp symbol))) - -(defcustom corfu-auto nil - "Enable auto completion." - :type 'boolean) - -(defgroup corfu-faces nil - "Faces used by Corfu." - :group 'corfu - :group 'faces) - -(defface corfu-default - '((((class color) (min-colors 88) (background dark)) :background "#191a1b") - (((class color) (min-colors 88) (background light)) :background "#f0f0f0") - (t :background "gray")) - "Default face, foreground and background colors used for the popup.") - -(defface corfu-current - '((((class color) (min-colors 88) (background dark)) - :background "#00415e" :foreground "white") - (((class color) (min-colors 88) (background light)) - :background "#c0efff" :foreground "black") - (t :background "blue" :foreground "white")) - "Face used to highlight the currently selected candidate.") - -(defface corfu-bar - '((((class color) (min-colors 88) (background dark)) :background "#a8a8a8") - (((class color) (min-colors 88) (background light)) :background "#505050") - (t :background "gray")) - "The background color is used for the scrollbar indicator.") - -(defface corfu-border - '((((class color) (min-colors 88) (background dark)) :background "#323232") - (((class color) (min-colors 88) (background light)) :background "#d7d7d7") - (t :background "gray")) - "The background color used for the thin border.") - -(defface corfu-annotations - '((t :inherit completions-annotations)) - "Face used for annotations.") - -(defface corfu-deprecated - '((t :inherit shadow :strike-through t)) - "Face used for deprecated candidates.") - -(defvar-keymap corfu-mode-map - :doc "Keymap used when `corfu-mode' is active.") - -(defvar-keymap corfu-map - :doc "Keymap used when popup is shown." - "<remap> <move-beginning-of-line>" #'corfu-prompt-beginning - "<remap> <move-end-of-line>" #'corfu-prompt-end - "<remap> <beginning-of-buffer>" #'corfu-first - "<remap> <end-of-buffer>" #'corfu-last - "<remap> <scroll-down-command>" #'corfu-scroll-down - "<remap> <scroll-up-command>" #'corfu-scroll-up - "<remap> <next-line>" #'corfu-next - "<remap> <previous-line>" #'corfu-previous - "<remap> <completion-at-point>" #'corfu-complete - "<remap> <keyboard-escape-quit>" #'corfu-reset - "<down>" #'corfu-next - "<up>" #'corfu-previous - ;; XXX C-a is bound because of Eshell. - ;; Ideally Eshell would remap move-beginning-of-line. - "C-a" #'corfu-prompt-beginning - ;; XXX [tab] is bound because of org-mode - ;; The binding should be removed from org-mode-map. - "<tab>" #'corfu-complete - "M-n" #'corfu-next - "M-p" #'corfu-previous - "C-g" #'corfu-quit - "RET" #'corfu-insert - "TAB" #'corfu-complete - "M-g" 'corfu-info-location - "M-h" 'corfu-info-documentation - "M-SPC" #'corfu-insert-separator) - -(defvar corfu--auto-timer nil - "Auto completion timer.") - -(defvar-local corfu--candidates nil - "List of candidates.") - -(defvar-local corfu--metadata nil - "Completion metadata.") - -(defvar-local corfu--base "" - "Base string, which is concatenated with the candidate.") - -(defvar-local corfu--total 0 - "Length of the candidate list `corfu--candidates'.") - -(defvar-local corfu--hilit #'identity - "Lazy candidate highlighting function.") - -(defvar-local corfu--index -1 - "Index of current candidate or negative for prompt selection.") - -(defvar-local corfu--preselect -1 - "Index of preselected candidate, negative for prompt selection.") - -(defvar-local corfu--scroll 0 - "Scroll position.") - -(defvar-local corfu--input nil - "Cons of last prompt contents and point.") - -(defvar-local corfu--preview-ov nil - "Current candidate overlay.") - -(defvar-local corfu--extra nil - "Extra completion properties.") - -(defvar-local corfu--change-group nil - "Undo change group.") - -(defvar corfu--frame nil - "Popup frame.") - -(defconst corfu--state-vars - '(corfu--base - corfu--candidates - corfu--hilit - corfu--index - corfu--preselect - corfu--scroll - corfu--input - corfu--total - corfu--preview-ov - corfu--extra - corfu--change-group - corfu--metadata) - "Buffer-local state variables used by Corfu.") - -(defvar corfu--frame-parameters - '((no-accept-focus . t) - (no-focus-on-map . t) - (min-width . t) - (min-height . t) - (border-width . 0) - (child-frame-border-width . 1) - (left-fringe . 0) - (right-fringe . 0) - (vertical-scroll-bars . nil) - (horizontal-scroll-bars . nil) - (menu-bar-lines . 0) - (tool-bar-lines . 0) - (tab-bar-lines . 0) - (no-other-frame . t) - (unsplittable . t) - (undecorated . t) - (cursor-type . nil) - (no-special-glyphs . t) - (desktop-dont-save . t)) - "Default child frame parameters.") - -(defvar corfu--buffer-parameters - '((mode-line-format . nil) - (header-line-format . nil) - (tab-line-format . nil) - (tab-bar-format . nil) ;; Emacs 28 tab-bar-format - (frame-title-format . "") - (truncate-lines . t) - (cursor-in-non-selected-windows . nil) - (cursor-type . nil) - (show-trailing-whitespace . nil) - (display-line-numbers . nil) - (left-fringe-width . nil) - (right-fringe-width . nil) - (left-margin-width . 0) - (right-margin-width . 0) - (fringes-outside-margins . 0) - (fringe-indicator-alist . nil) - (indicate-empty-lines . nil) - (indicate-buffer-boundaries . nil) - (buffer-read-only . t)) - "Default child frame buffer parameters.") - -(defvar corfu--mouse-ignore-map - (let ((map (make-sparse-keymap))) - (dotimes (i 7) - (dolist (k '(mouse down-mouse drag-mouse double-mouse triple-mouse)) - (keymap-set map (format "<%s-%s>" k (1+ i)) #'ignore))) - map) - "Ignore all mouse clicks.") - -(defun corfu--capf-wrapper (fun &optional prefix) - "Wrapper for `completion-at-point' FUN. -The wrapper determines if the Capf is applicable at the current -position and performs sanity checking on the returned result. -For non-exclusive Capfs wrapper additionally checks if the -current input can be completed successfully. PREFIX is a prefix -length override, set to t for manual completion." - (pcase (funcall fun) - ((and res `(,beg ,end ,table . ,plist)) - (and (integer-or-marker-p beg) ;; Valid Capf result - (<= beg (point) end) ;; Sanity checking - ;; When auto completing, check the prefix length! - (let ((len (or prefix - (plist-get plist :company-prefix-length) - (- (point) beg)))) - (or (eq len t) (>= len corfu-auto-prefix))) - ;; For non-exclusive Capfs, check for valid completion. - (or (not (eq 'no (plist-get plist :exclusive))) - (let* ((str (buffer-substring-no-properties beg end)) - (pt (- (point) beg)) - (pred (plist-get plist :predicate)) - (md (completion-metadata (substring str 0 pt) table pred))) - ;; We use `completion-try-completion' to check if there are - ;; completions. The upstream `completion--capf-wrapper' uses - ;; `try-completion' which is incorrect since it only checks for - ;; prefix completions. - (completion-try-completion str table pred pt md))) - (cons fun res))))) - -(defun corfu--make-buffer (name) - "Create buffer with NAME." - (let ((fr face-remapping-alist) - (ls line-spacing) - (buffer (get-buffer-create name))) - (with-current-buffer buffer - ;;; XXX HACK install mouse ignore map - (use-local-map corfu--mouse-ignore-map) - (dolist (var corfu--buffer-parameters) - (set (make-local-variable (car var)) (cdr var))) - (setq-local face-remapping-alist (copy-tree fr) - line-spacing ls) - (cl-pushnew 'corfu-default (alist-get 'default face-remapping-alist)) - buffer))) - -(defvar x-gtk-resize-child-frames) ;; Not present on non-gtk builds -(defvar corfu--gtk-resize-child-frames - (let ((case-fold-search t)) - (and - ;; XXX HACK to fix resizing on gtk3/gnome taken from posframe.el - ;; More information: - ;; * https://github.com/minad/corfu/issues/17 - ;; * https://gitlab.gnome.org/GNOME/mutter/-/issues/840 - ;; * https://lists.gnu.org/archive/html/emacs-devel/2020-02/msg00001.html - (string-match-p "gtk3" system-configuration-features) - (string-match-p "gnome\\|cinnamon" - (or (getenv "XDG_CURRENT_DESKTOP") - (getenv "DESKTOP_SESSION") "")) - 'resize-mode))) - -;; Function adapted from posframe.el by tumashu -(defun corfu--make-frame (frame x y width height buffer) - "Show BUFFER in child frame at X/Y with WIDTH/HEIGHT. -FRAME is the existing frame." - (when-let (((frame-live-p frame)) - (timer (frame-parameter frame 'corfu--hide-timer))) - (cancel-timer timer) - (set-frame-parameter frame 'corfu--hide-timer nil)) - (let* ((window-min-height 1) - (window-min-width 1) - (inhibit-redisplay t) - (x-gtk-resize-child-frames corfu--gtk-resize-child-frames) - (before-make-frame-hook) - (after-make-frame-functions) - (parent (window-frame))) - (unless (and (frame-live-p frame) - (eq (frame-parent frame) parent) - ;; If there is more than one window, `frame-root-window' may - ;; return nil. Recreate the frame in this case. - (window-live-p (frame-root-window frame))) - (when frame (delete-frame frame)) - (setq frame (make-frame - `((parent-frame . ,parent) - (minibuffer . ,(minibuffer-window parent)) - (width . 0) (height . 0) (visibility . nil) - ,@corfu--frame-parameters)))) - ;; XXX HACK Setting the same frame-parameter/face-background is not a nop. - ;; Check before applying the setting. Without the check, the frame flickers - ;; on Mac. We have to apply the face background before adjusting the frame - ;; parameter, otherwise the border is not updated. - (let* ((face (if (facep 'child-frame-border) 'child-frame-border 'internal-border)) - (new (face-attribute 'corfu-border :background nil 'default))) - (unless (equal (face-attribute face :background frame 'default) new) - (set-face-background face new frame))) - ;; Reset frame parameters if they changed. For example `tool-bar-mode' - ;; overrides the parameter `tool-bar-lines' for every frame, including child - ;; frames. The child frame API is a pleasure to work with. It is full of - ;; lovely surprises. - (when-let ((params (frame-parameters frame)) - (reset (seq-remove - (lambda (p) (equal (alist-get (car p) params) (cdr p))) - `((background-color - . ,(face-attribute 'corfu-default :background nil 'default)) - ;; Set `internal-border-width' for Emacs 27 - (internal-border-width - . ,(alist-get 'child-frame-border-width corfu--frame-parameters)) - (font . ,(frame-parameter parent 'font)) - ,@corfu--frame-parameters)))) - (modify-frame-parameters frame reset)) - (let ((win (frame-root-window frame))) - (unless (eq (window-buffer win) buffer) - (set-window-buffer win buffer)) - ;; Disallow selection of root window (#63) - (set-window-parameter win 'no-delete-other-windows t) - (set-window-parameter win 'no-other-window t) - ;; Mark window as dedicated to prevent frame reuse (#60) - (set-window-dedicated-p win t)) - (redirect-frame-focus frame parent) - (set-frame-size frame width height t) - (unless (equal (frame-position frame) (cons x y)) - (set-frame-position frame x y))) - (make-frame-visible frame)) - -(defun corfu--hide-frame-deferred (frame) - "Deferred hiding of child FRAME." - (when (and (frame-live-p frame) (frame-visible-p frame)) - (set-frame-parameter frame 'corfu--hide-timer nil) - (make-frame-invisible frame) - (with-current-buffer (window-buffer (frame-root-window frame)) - (with-silent-modifications - (erase-buffer))))) - -(defun corfu--hide-frame (frame) - "Hide child FRAME." - (when (and (frame-live-p frame) (frame-visible-p frame) - (not (frame-parameter frame 'corfu--hide-timer))) - (set-frame-parameter frame 'corfu--hide-timer - (run-at-time 0 nil #'corfu--hide-frame-deferred frame)))) - -(defun corfu--move-to-front (elem list) - "Move ELEM to front of LIST." - (if-let ((found (member elem list))) - (nconc (list (car found)) (delq (setcar found nil) list)) - list)) - -(defun corfu--filter-completions (&rest args) - "Compute all completions for ARGS with lazy highlighting." - (defvar completion-lazy-hilit) - (defvar completion-lazy-hilit-fn) - (cl-letf* ((completion-lazy-hilit t) - (completion-lazy-hilit-fn nil) - ((symbol-function #'completion-hilit-commonality) - (lambda (cands prefix &optional base) - (setq completion-lazy-hilit-fn - (lambda (x) (car (completion-hilit-commonality (list x) prefix base)))) - (and cands (nconc cands base))))) - (if (eval-when-compile (>= emacs-major-version 30)) - (cons (apply #'completion-all-completions args) completion-lazy-hilit-fn) - (cl-letf* ((orig-pcm (symbol-function #'completion-pcm--hilit-commonality)) - (orig-flex (symbol-function #'completion-flex-all-completions)) - ((symbol-function #'completion-flex-all-completions) - (lambda (&rest args) - ;; Unfortunately for flex we have to undo the lazy highlighting, since flex uses - ;; the completion-score for sorting, which is applied during highlighting. - (cl-letf (((symbol-function #'completion-pcm--hilit-commonality) orig-pcm)) - (apply orig-flex args)))) - ((symbol-function #'completion-pcm--hilit-commonality) - (lambda (pattern cands) - (setq completion-lazy-hilit-fn - (lambda (x) - ;; `completion-pcm--hilit-commonality' sometimes throws an internal error - ;; for example when entering "/sudo:://u". - (condition-case nil - (car (completion-pcm--hilit-commonality pattern (list x))) - (t x)))) - cands))) - (cons (apply #'completion-all-completions args) completion-lazy-hilit-fn))))) - -(defsubst corfu--length-string< (x y) - "Sorting predicate which compares X and Y first by length then by `string<'." - (or (< (length x) (length y)) (and (= (length x) (length y)) (string< x y)))) - -(defmacro corfu--partition! (list form) - "Evaluate FORM for every element and partition LIST." - (cl-with-gensyms (head1 head2 tail1 tail2) - `(let* ((,head1 (cons nil nil)) - (,head2 (cons nil nil)) - (,tail1 ,head1) - (,tail2 ,head2)) - (while ,list - (if (let ((it (car ,list))) ,form) - (progn - (setcdr ,tail1 ,list) - (pop ,tail1)) - (setcdr ,tail2 ,list) - (pop ,tail2)) - (pop ,list)) - (setcdr ,tail1 (cdr ,head2)) - (setcdr ,tail2 nil) - (setq ,list (cdr ,head1))))) - -(defun corfu--move-prefix-candidates-to-front (field candidates) - "Move CANDIDATES which match prefix of FIELD to the beginning." - (let* ((word (substring field 0 - (seq-position field corfu-separator))) - (len (length word))) - (corfu--partition! - candidates - (and (>= (length it) len) - (eq t (compare-strings word 0 len it 0 len - completion-ignore-case)))))) - -(defun corfu--sort-function () - "Return the sorting function." - (or corfu-sort-override-function - (corfu--metadata-get 'display-sort-function) - corfu-sort-function)) - -(defun corfu--recompute (str pt table pred) - "Recompute state from STR, PT, TABLE and PRED." - (pcase-let* ((before (substring str 0 pt)) - (after (substring str pt)) - (corfu--metadata (completion-metadata before table pred)) - ;; bug#47678: `completion-boundaries' fails for `partial-completion' - ;; if the cursor is moved between the slashes of "~//". - ;; See also vertico.el which has the same issue. - (bounds (condition-case nil - (completion-boundaries before table pred after) - (t (cons 0 (length after))))) - (field (substring str (car bounds) (+ pt (cdr bounds)))) - (completing-file (eq (corfu--metadata-get 'category) 'file)) - (`(,all . ,hl) (corfu--filter-completions str table pred pt corfu--metadata)) - (base (or (when-let ((z (last all))) (prog1 (cdr z) (setcdr z nil))) 0)) - (corfu--base (substring str 0 base))) - ;; Filter the ignored file extensions. We cannot use modified predicate for - ;; this filtering, since this breaks the special casing in the - ;; `completion-file-name-table' for `file-exists-p' and `file-directory-p'. - (when completing-file (setq all (completion-pcm--filename-try-filter all))) - (setq all (delete-consecutive-dups (funcall (or (corfu--sort-function) #'identity) all))) - (setq all (corfu--move-prefix-candidates-to-front field all)) - (when (and completing-file (not (string-suffix-p "/" field))) - (setq all (corfu--move-to-front (concat field "/") all))) - (setq all (corfu--move-to-front field all)) - `((corfu--base . ,corfu--base) - (corfu--metadata . ,corfu--metadata) - (corfu--candidates . ,all) - (corfu--total . ,(length all)) - (corfu--hilit . ,(or hl #'identity)) - (corfu--preselect . ,(if (or (eq corfu-preselect 'prompt) (not all) - (and completing-file (eq corfu-preselect 'directory) - (= (length corfu--base) (length str)) - (test-completion str table pred)) - (and (eq corfu-preselect 'valid) - (not (equal field (car all))) - (not (and completing-file (equal (concat field "/") (car all)))) - (test-completion str table pred))) - -1 0))))) - -(defun corfu--update (&optional interruptible) - "Update state, optionally INTERRUPTIBLE." - (pcase-let* ((`(,beg ,end ,table ,pred) completion-in-region--data) - (pt (- (point) beg)) - (str (buffer-substring-no-properties beg end)) - (input (cons str pt))) - (unless (equal corfu--input input) - ;; Redisplay such that the input becomes immediately visible before the - ;; expensive candidate recomputation is performed (Issue #48). See also - ;; corresponding vertico#89. - (when interruptible (redisplay)) - ;; Bind non-essential=t to prevent Tramp from opening new connections, - ;; without the user explicitly requesting it via M-TAB. - (pcase (let ((non-essential t)) - ;; XXX Guard against errors during candidate generation. - ;; bug#61274: `dabbrev-capf' signals errors. - (condition-case err - (if interruptible - (while-no-input (corfu--recompute str pt table pred)) - (corfu--recompute str pt table pred)) - (error - (message "Corfu completion error: %s" (error-message-string err)) - t))) - ('nil (keyboard-quit)) - ((and state (pred consp)) - (dolist (s state) (set (car s) (cdr s))) - (setq corfu--input input - corfu--index corfu--preselect)))) - input)) - -(defun corfu--match-symbol-p (pattern sym) - "Return non-nil if SYM is matching an element of the PATTERN list." - (and (symbolp sym) - (cl-loop with case-fold-search = nil - for x in pattern - thereis (if (symbolp x) - (eq sym x) - (string-match-p x (symbol-name sym)))))) - -(defun corfu--metadata-get (prop) - "Return PROP from completion metadata." - ;; Note: Do not use `completion-metadata-get' in order to avoid Marginalia. - ;; The Marginalia annotators are too heavy for the Corfu popup! - (cdr (assq prop corfu--metadata))) - -(defun corfu--format-candidates (cands) - "Format annotated CANDS." - (setq cands - (cl-loop for c in cands collect - (cl-loop for s in c collect - (replace-regexp-in-string "[ \t]*\n[ \t]*" " " s)))) - (let* ((cw (cl-loop for x in cands maximize (string-width (car x)))) - (pw (cl-loop for x in cands maximize (string-width (cadr x)))) - (sw (cl-loop for x in cands maximize (string-width (caddr x)))) - (width (+ pw cw sw)) - ;; -4 because of margins and some additional safety - (max-width (min corfu-max-width (- (frame-width) 4)))) - (when (> width max-width) - (setq sw (max 0 (- max-width pw cw)) - width (+ pw cw sw))) - (when (< width corfu-min-width) - (setq cw (+ cw (- corfu-min-width width)) - width corfu-min-width)) - (setq width (min width max-width)) - (list pw width - (cl-loop for (cand prefix suffix) in cands collect - (truncate-string-to-width - (concat prefix - (make-string (max 0 (- pw (string-width prefix))) ?\s) - cand - (when (/= sw 0) - (make-string - (+ (max 0 (- cw (string-width cand))) - (max 0 (- sw (string-width suffix)))) - ?\s)) - suffix) - width))))) - -(defun corfu--compute-scroll () - "Compute new scroll position." - (let ((off (max (min corfu-scroll-margin (/ corfu-count 2)) 0)) - (corr (if (= corfu-scroll-margin (/ corfu-count 2)) (1- (mod corfu-count 2)) 0))) - (setq corfu--scroll (min (max 0 (- corfu--total corfu-count)) - (max 0 (+ corfu--index off 1 (- corfu-count)) - (min (- corfu--index off corr) corfu--scroll)))))) - -(defun corfu--candidates-popup (pos) - "Show candidates popup at POS." - (corfu--compute-scroll) - (pcase-let* ((last (min (+ corfu--scroll corfu-count) corfu--total)) - (bar (ceiling (* corfu-count corfu-count) corfu--total)) - (lo (min (- corfu-count bar 1) (floor (* corfu-count corfu--scroll) corfu--total))) - (`(,mf . ,acands) (corfu--affixate - (cl-loop repeat corfu-count - for c in (nthcdr corfu--scroll corfu--candidates) - collect (funcall corfu--hilit (substring c))))) - (`(,pw ,width ,fcands) (corfu--format-candidates acands)) - ;; Disable the left margin if a margin formatter is active. - (corfu-left-margin-width (if mf 0 corfu-left-margin-width))) - ;; Nonlinearity at the end and the beginning - (when (/= corfu--scroll 0) - (setq lo (max 1 lo))) - (when (/= last corfu--total) - (setq lo (min (- corfu-count bar 2) lo))) - (corfu--popup-show pos pw width fcands (- corfu--index corfu--scroll) - (and (> corfu--total corfu-count) lo) bar))) - -(defun corfu--preview-current (beg end) - "Show current candidate as overlay given BEG and END." - (when-let ((cand (and corfu-preview-current (>= corfu--index 0) - (/= corfu--index corfu--preselect) - (nth corfu--index corfu--candidates)))) - (setq beg (+ beg (length corfu--base)) - corfu--preview-ov (make-overlay beg end nil)) - (overlay-put corfu--preview-ov 'priority 1000) - (overlay-put corfu--preview-ov 'window (selected-window)) - (overlay-put corfu--preview-ov (if (= beg end) 'after-string 'display) cand))) - -(defun corfu--continue-p () - "Check if completion should be continued after a command. -Corfu bails out if the currently selected buffer changed -unexpectedly, if point moved to an unexpected position, if the -input doesn't satisfy the `completion-in-region-mode--predicate' -or if the last invoked command is not listed in -`corfu-continue-commands'." - (pcase-let ((pt (point)) - (buf (current-buffer)) - (`(,beg ,end . ,_) completion-in-region--data)) - (and beg end - (eq buf (marker-buffer beg)) - (eq buf (window-buffer)) - ;; Check ranges - (<= beg pt end) - (save-excursion - (goto-char beg) - (<= (pos-bol) pt (pos-eol))) - (or - ;; We keep Corfu alive if a `overriding-terminal-local-map' is - ;; installed, e.g., the `universal-argument-map'. It would be good to - ;; think about a better criterion instead. Unfortunately relying on - ;; `this-command' alone is insufficient, since the value of - ;; `this-command' gets clobbered in the case of transient keymaps. - overriding-terminal-local-map - ;; Check if it is an explicitly listed continue command - (corfu--match-symbol-p corfu-continue-commands this-command) - (and (or (not corfu--input) (< beg end)) ;; Check for empty input - (or (not corfu-quit-at-boundary) ;; Check separator or predicate - (and (eq corfu-quit-at-boundary 'separator) - (or (eq this-command #'corfu-insert-separator) - ;; with separator, any further chars allowed - (seq-contains-p (car corfu--input) corfu-separator))) - (funcall completion-in-region-mode--predicate))))))) - -(defun corfu--window-change (_) - "Window and buffer change hook which quits Corfu." - (let ((buf (current-buffer)) - (beg (car completion-in-region--data))) - (unless (and beg (eq buf (marker-buffer beg)) (eq buf (window-buffer))) - (corfu-quit)))) - -(defun corfu--post-command () - "Refresh Corfu after last command." - (if (corfu--continue-p) - (corfu--exhibit) - (corfu-quit)) - (when corfu-auto - (corfu--auto-post-command))) - -(defun corfu--goto (index) - "Go to candidate with INDEX." - (setq corfu--index (max corfu--preselect (min index (1- corfu--total))))) - -(defun corfu--done (str status) - "Call the `:exit-function' with STR and STATUS and exit completion." - (let ((exit (plist-get corfu--extra :exit-function))) - ;; For successful completions, amalgamate undo operations, - ;; such that completion can be undone in a single step. - (undo-amalgamate-change-group corfu--change-group) - (corfu-quit) - (when exit (funcall exit str status)))) - -(defun corfu--setup () - "Setup Corfu completion state." - (setq corfu--extra completion-extra-properties) - (completion-in-region-mode 1) - (activate-change-group (setq corfu--change-group (prepare-change-group))) - (setcdr (assq #'completion-in-region-mode minor-mode-overriding-map-alist) corfu-map) - (add-hook 'pre-command-hook #'corfu--prepare nil 'local) - (add-hook 'window-selection-change-functions #'corfu--window-change nil 'local) - (add-hook 'window-buffer-change-functions #'corfu--window-change nil 'local) - (add-hook 'post-command-hook #'corfu--post-command) - ;; Disable default post-command handling, since we have our own - ;; checks in `corfu--post-command'. - (remove-hook 'post-command-hook #'completion-in-region--postch) - (let ((sym (make-symbol "corfu--teardown")) - (buf (current-buffer))) - (fset sym (lambda () - ;; Ensure that the tear-down runs in the correct buffer, if still alive. - (unless completion-in-region-mode - (remove-hook 'completion-in-region-mode-hook sym) - (with-current-buffer (if (buffer-live-p buf) buf (current-buffer)) - (corfu--teardown))))) - (add-hook 'completion-in-region-mode-hook sym))) - -(defun corfu--in-region (&rest args) - "Corfu completion in region function called with ARGS." - ;; XXX We can get an endless loop when `completion-in-region-function' is set - ;; globally to `corfu--in-region'. This should never happen. - (apply (if (corfu--popup-support-p) #'corfu--in-region-1 - (default-value 'completion-in-region-function)) - args)) - -(defun corfu--in-region-1 (beg end table &optional pred) - "Complete in region, see `completion-in-region' for BEG, END, TABLE, PRED." - (barf-if-buffer-read-only) - ;; Restart the completion. This can happen for example if C-M-/ - ;; (`dabbrev-completion') is pressed while the Corfu popup is already open. - (when completion-in-region-mode (corfu-quit)) - (let* ((pt (max 0 (- (point) beg))) - (str (buffer-substring-no-properties beg end)) - (metadata (completion-metadata (substring str 0 pt) table pred)) - (exit (plist-get completion-extra-properties :exit-function)) - (threshold (completion--cycle-threshold metadata)) - (completion-in-region-mode-predicate - (or completion-in-region-mode-predicate #'always))) - (pcase (completion-try-completion str table pred pt metadata) - ('nil (corfu--message "No match") nil) - ('t (goto-char end) - (corfu--message "Sole match") - (when exit (funcall exit str 'finished)) - t) - (`(,newstr . ,newpt) - (let* ((state (corfu--recompute str pt table pred)) - (base (alist-get 'corfu--base state)) - (total (alist-get 'corfu--total state)) - (candidates (alist-get 'corfu--candidates state))) - (unless (markerp beg) (setq beg (copy-marker beg))) - (setq end (copy-marker end t) - completion-in-region--data (list beg end table pred)) - (unless (equal str newstr) - ;; bug#55205: completion--replace removes properties! - (completion--replace beg end (concat newstr))) - (goto-char (+ beg newpt)) - (if (= total 1) - ;; If completion is finished and cannot be further completed, - ;; return 'finished. Otherwise setup the Corfu popup. - (cond - ((consp (completion-try-completion - newstr table pred newpt - (completion-metadata newstr table pred))) - (corfu--setup)) - (exit (funcall exit newstr 'finished))) - (if (or (= total 0) (not threshold) - (and (not (eq threshold t)) (< threshold total))) - (corfu--setup) - (corfu--cycle-candidates total candidates (+ (length base) beg) end) - ;; Do not show Corfu when "trivially" cycling, i.e., - ;; when the completion is finished after the candidate. - (unless (equal (completion-boundaries (car candidates) table pred "") - '(0 . 0)) - (corfu--setup))))) - t)))) - -(defun corfu--message (&rest msg) - "Show completion MSG." - (let (message-log-max) (apply #'message msg))) - -(defun corfu--cycle-candidates (total cands beg end) - "Cycle between TOTAL number of CANDS. -See `completion-in-region' for the arguments BEG, END, TABLE, PRED." - (let* ((idx 0) - (map (make-sparse-keymap)) - (replace (lambda () - (interactive) - ;; bug#55205: completion--replace removes properties! - (completion--replace beg end (concat (nth idx cands))) - (corfu--message "Cycling %d/%d..." (1+ idx) total) - (setq idx (mod (1+ idx) total)) - (set-transient-map map)))) - (define-key map [remap completion-at-point] replace) - (define-key map [remap corfu-complete] replace) - (define-key map (vector last-command-event) replace) - (funcall replace))) - -(defun corfu--auto-complete-deferred (&optional tick) - "Initiate auto completion if TICK did not change." - (setq corfu--auto-timer nil) - (when (and (not completion-in-region-mode) - (or (not tick) (equal tick (corfu--auto-tick)))) - (pcase (while-no-input ;; Interruptible Capf query - (run-hook-wrapped 'completion-at-point-functions #'corfu--capf-wrapper)) - (`(,fun ,beg ,end ,table . ,plist) - (let ((completion-in-region-mode-predicate - (lambda () - (when-let ((newbeg (car-safe (funcall fun)))) - (= newbeg beg)))) - (completion-extra-properties plist)) - (setq completion-in-region--data - (list (if (markerp beg) beg (copy-marker beg)) - (copy-marker end t) - table - (plist-get plist :predicate))) - (corfu--setup) - (corfu--exhibit 'auto)))))) - -(defun corfu--auto-post-command () - "Post command hook which initiates auto completion." - (when corfu--auto-timer - (cancel-timer corfu--auto-timer) - (setq corfu--auto-timer nil)) - (when (and (not completion-in-region-mode) - (not defining-kbd-macro) - (not buffer-read-only) - (corfu--match-symbol-p corfu-auto-commands this-command) - (corfu--popup-support-p)) - (if (<= corfu-auto-delay 0) - (corfu--auto-complete-deferred) - ;; Do not use idle timer since this leads to unpredictable pauses, in - ;; particular with `flyspell-mode'. - (setq corfu--auto-timer - (run-at-time corfu-auto-delay nil - #'corfu--auto-complete-deferred (corfu--auto-tick)))))) - -(defun corfu--auto-tick () - "Return the current tick/status of the buffer. -Auto completion is only performed if the tick did not change." - (list (selected-window) (current-buffer) (buffer-chars-modified-tick) (point))) - -(cl-defgeneric corfu--popup-show (pos off width lines &optional curr lo bar) - "Show LINES as popup at POS - OFF. -WIDTH is the width of the popup. -The current candidate CURR is highlighted. -A scroll bar is displayed from LO to LO+BAR." - (let ((lh (default-line-height))) - (with-current-buffer (corfu--make-buffer " *corfu*") - (let* ((ch (default-line-height)) - (cw (default-font-width)) - (ml (ceiling (* cw corfu-left-margin-width))) - (mr (ceiling (* cw corfu-right-margin-width))) - (bw (ceiling (min mr (* cw corfu-bar-width)))) - (marginl (and (> ml 0) (propertize " " 'display `(space :width (,ml))))) - (marginr (and (> mr 0) (propertize " " 'display `(space :align-to right)))) - (sbar (when (> bw 0) - (concat (propertize " " 'display `(space :align-to (- right (,mr)))) - (propertize " " 'display `(space :width (,(- mr bw)))) - (propertize " " 'face 'corfu-bar 'display `(space :width (,bw)))))) - (pos (posn-x-y pos)) - (width (+ (* width cw) ml mr)) - ;; XXX HACK: Minimum popup height must be at least 1 line of the - ;; parent frame (#261). - (height (max lh (* (length lines) ch))) - (edge (window-inside-pixel-edges)) - (border (alist-get 'child-frame-border-width corfu--frame-parameters)) - (x (max 0 (min (+ (car edge) (- (or (car pos) 0) ml (* cw off) border)) - (- (frame-pixel-width) width)))) - (yb (+ (cadr edge) (window-tab-line-height) (or (cdr pos) 0) lh)) - (y (if (> (+ yb (* corfu-count ch) lh lh) (frame-pixel-height)) - (- yb height lh border border) - yb)) - (row 0)) - (with-silent-modifications - (erase-buffer) - (insert (mapconcat (lambda (line) - (let ((str (concat marginl line - (if (and lo (<= lo row (+ lo bar))) - sbar - marginr)))) - (when (eq row curr) - (add-face-text-property - 0 (length str) 'corfu-current 'append str)) - (cl-incf row) - str)) - lines "\n")) - (goto-char (point-min))) - (setq corfu--frame (corfu--make-frame corfu--frame x y - width height (current-buffer))))))) - -(cl-defgeneric corfu--popup-hide () - "Hide Corfu popup." - (corfu--hide-frame corfu--frame)) - -(cl-defgeneric corfu--popup-support-p () - "Return non-nil if child frames are supported." - (display-graphic-p)) - -(cl-defgeneric corfu--insert (status) - "Insert current candidate, exit with STATUS if non-nil." - (pcase-let* ((`(,beg ,end . ,_) completion-in-region--data) - (str (buffer-substring-no-properties beg end))) - ;; XXX There is a small bug here, depending on interpretation. - ;; When completing "~/emacs/master/li|/calc" where "|" is the - ;; cursor, then the candidate only includes the prefix - ;; "~/emacs/master/lisp/", but not the suffix "/calc". Default - ;; completion has the same problem when selecting in the - ;; *Completions* buffer. See bug#48356. - (setq str (concat corfu--base (substring-no-properties - (nth corfu--index corfu--candidates)))) - ;; bug#55205: completion--replace removes properties! - (completion--replace beg end (concat str)) - (corfu--goto -1) ;; Reset selection, but continue completion. - (when status (corfu--done str status)))) ;; Exit with status - -(cl-defgeneric corfu--affixate (cands) - "Annotate CANDS with annotation function." - (setq cands - (if-let ((aff (or (corfu--metadata-get 'affixation-function) - (plist-get corfu--extra :affixation-function)))) - (funcall aff cands) - (if-let ((ann (or (corfu--metadata-get 'annotation-function) - (plist-get corfu--extra :annotation-function)))) - (cl-loop for cand in cands collect - (let ((suffix (or (funcall ann cand) ""))) - ;; The default completion UI adds the - ;; `completions-annotations' face if no other faces are - ;; present. We use a custom `corfu-annotations' face to - ;; allow further styling which fits better for popups. - (unless (text-property-not-all 0 (length suffix) 'face nil suffix) - (setq suffix (propertize suffix 'face 'corfu-annotations))) - (list cand "" suffix))) - (cl-loop for cand in cands collect (list cand "" ""))))) - (let* ((dep (plist-get corfu--extra :company-deprecated)) - (completion-extra-properties corfu--extra) - (mf (run-hook-with-args-until-success 'corfu-margin-formatters corfu--metadata))) - (cl-loop for x in cands for (c . _) = x do - (when mf - (setf (cadr x) (funcall mf c))) - (when (and dep (funcall dep c)) - (setcar x (setq c (substring c))) - (add-face-text-property 0 (length c) 'corfu-deprecated 'append c))) - (cons mf cands))) - -(cl-defgeneric corfu--prepare () - "Insert selected candidate unless command is marked to continue completion." - (when corfu--preview-ov - (delete-overlay corfu--preview-ov) - (setq corfu--preview-ov nil)) - ;; Ensure that state is initialized before next Corfu command - (when (and (symbolp this-command) (string-prefix-p "corfu-" (symbol-name this-command))) - (corfu--update)) - ;; If the next command is not listed in `corfu-continue-commands', insert the - ;; currently selected candidate and bail out of completion. This way you can - ;; continue typing after selecting a candidate. The candidate will be inserted - ;; and your new input will be appended. - (when (and (eq corfu-preview-current 'insert) - (/= corfu--index corfu--preselect) - ;; See the comment about `overriding-local-map' in `corfu--post-command'. - (not (or overriding-terminal-local-map - (corfu--match-symbol-p corfu-continue-commands this-command)))) - (corfu--insert 'exact))) - -(cl-defgeneric corfu--exhibit (&optional auto) - "Exhibit Corfu UI. -AUTO is non-nil when initializing auto completion." - (pcase-let ((`(,beg ,end ,table ,pred) completion-in-region--data) - (`(,str . ,pt) (corfu--update 'interruptible))) - (cond - ;; 1) Single exactly matching candidate and no further completion is possible. - ((and (not (equal str "")) - (equal (car corfu--candidates) str) (not (cdr corfu--candidates)) - (not (consp (completion-try-completion str table pred pt corfu--metadata))) - (or auto corfu-on-exact-match)) - ;; Quit directly when initializing auto completion. - (if (or auto (eq corfu-on-exact-match 'quit)) - (corfu-quit) - (corfu--done str 'finished))) - ;; 2) There exist candidates => Show candidates popup. - (corfu--candidates - (let ((pos (posn-at-point (+ beg (length corfu--base))))) - (corfu--preview-current beg end) - (corfu--candidates-popup pos))) - ;; 3) No candidates & corfu-quit-no-match & initialized => Confirmation popup. - ((pcase-exhaustive corfu-quit-no-match - ('t nil) - ('nil corfu--input) - ('separator (seq-contains-p (car corfu--input) corfu-separator))) - (corfu--popup-show (posn-at-point beg) 0 8 '(#("No match" 0 8 (face italic))))) - ;; 4) No candidates & auto completing or initialized => Quit. - ((or auto corfu--input) (corfu-quit))))) - -(cl-defgeneric corfu--teardown () - "Tear-down Corfu." - (corfu--popup-hide) - (remove-hook 'window-selection-change-functions #'corfu--window-change 'local) - (remove-hook 'window-buffer-change-functions #'corfu--window-change 'local) - (remove-hook 'pre-command-hook #'corfu--prepare 'local) - (remove-hook 'post-command-hook #'corfu--post-command) - (when corfu--preview-ov (delete-overlay corfu--preview-ov)) - (accept-change-group corfu--change-group) - (mapc #'kill-local-variable corfu--state-vars)) - -(defun corfu-sort-length-alpha (list) - "Sort LIST by length and alphabetically." - (sort list #'corfu--length-string<)) - -(defun corfu-quit () - "Quit Corfu completion." - (interactive) - (completion-in-region-mode -1)) - -(defun corfu-reset () - "Reset Corfu completion. -This command can be executed multiple times by hammering the ESC key. If a -candidate is selected, unselect the candidate. Otherwise reset the input. If -there hasn't been any input, then quit." - (interactive) - (if (/= corfu--index corfu--preselect) - (progn - (corfu--goto -1) - (setq this-command #'corfu-first)) - ;; Cancel all changes and start new change group. - (pcase-let* ((`(,beg ,end . ,_) completion-in-region--data) - (str (buffer-substring-no-properties beg end))) - (cancel-change-group corfu--change-group) - (activate-change-group (setq corfu--change-group (prepare-change-group))) - ;; Quit when resetting, when input did not change. - (when (equal str (buffer-substring-no-properties beg end)) - (corfu-quit))))) - -(defun corfu-insert-separator () - "Insert a separator character, inhibiting quit on completion boundary. -See `corfu-separator' for more details." - (interactive) - (insert corfu-separator)) - -(defun corfu-next (&optional n) - "Go forward N candidates." - (interactive "p") - (let ((index (+ corfu--index (or n 1)))) - (corfu--goto - (cond - ((not corfu-cycle) index) - ((= corfu--total 0) -1) - ((< corfu--preselect 0) (1- (mod (1+ index) (1+ corfu--total)))) - (t (mod index corfu--total)))))) - -(defun corfu-previous (&optional n) - "Go backward N candidates." - (interactive "p") - (corfu-next (- (or n 1)))) - -(defun corfu-scroll-down (&optional n) - "Go back by N pages." - (interactive "p") - (corfu--goto (max 0 (- corfu--index (* (or n 1) corfu-count))))) - -(defun corfu-scroll-up (&optional n) - "Go forward by N pages." - (interactive "p") - (corfu-scroll-down (- (or n 1)))) - -(defun corfu-first () - "Go to first candidate. -If the first candidate is already selected, go to the prompt." - (interactive) - (corfu--goto (if (> corfu--index 0) 0 -1))) - -(defun corfu-last () - "Go to last candidate." - (interactive) - (corfu--goto (1- corfu--total))) - -(defun corfu-prompt-beginning (arg) - "Move to beginning of the prompt line. -If the point is already the beginning of the prompt move to the -beginning of the line. If ARG is not 1 or nil, move backward ARG - 1 -lines first." - (interactive "^p") - (let ((beg (car completion-in-region--data))) - (if (or (not (eq arg 1)) - (and (= corfu--preselect corfu--index) (= (point) beg))) - (move-beginning-of-line arg) - (corfu--goto -1) - (goto-char beg)))) - -(defun corfu-prompt-end (arg) - "Move to end of the prompt line. -If the point is already the end of the prompt move to the end of -the line. If ARG is not 1 or nil, move forward ARG - 1 lines -first." - (interactive "^p") - (let ((end (cadr completion-in-region--data))) - (if (or (not (eq arg 1)) - (and (= corfu--preselect corfu--index) (= (point) end))) - (move-end-of-line arg) - (corfu--goto -1) - (goto-char end)))) - -(defun corfu-complete () - "Try to complete current input. -If a candidate is selected, insert it." - (interactive) - (pcase-let ((`(,beg ,end ,table ,pred) completion-in-region--data)) - (if (>= corfu--index 0) - ;; Continue completion with selected candidate - (progn - (corfu--insert nil) - ;; Exit with status 'finished if input is a valid match and no further - ;; completion is possible. Furthermore treat the completion as - ;; finished if we are at the end of a boundary, even if other longer - ;; candidates would still match, since the user invoked `corfu-complete' - ;; with an explicitly selected candidate! - (let ((newstr (buffer-substring-no-properties beg end))) - (when (and (test-completion newstr table pred) - (or - (not (consp (completion-try-completion - newstr table pred (length newstr) - (completion-metadata newstr table pred)))) - (equal (completion-boundaries newstr table pred "") '(0 . 0)))) - (corfu--done newstr 'finished)))) - ;; Try to complete the current input string - (let* ((pt (max 0 (- (point) beg))) - (str (buffer-substring-no-properties beg end)) - (metadata (completion-metadata (substring str 0 pt) table pred))) - (pcase (completion-try-completion str table pred pt metadata) - ('t - (goto-char end) - (corfu--done str 'finished)) - (`(,newstr . ,newpt) - (unless (equal str newstr) - ;; bug#55205: completion--replace removes properties! - (completion--replace beg end (concat newstr))) - (goto-char (+ beg newpt)) - ;; Exit with status 'finished if input is a valid match - ;; and no further completion is possible. - (when (and (test-completion newstr table pred) - (not (consp (completion-try-completion - newstr table pred newpt - (completion-metadata (substring newstr 0 newpt) table pred))))) - (corfu--done newstr 'finished)))))))) - -(defun corfu-insert () - "Insert current candidate. -Quit if no candidate is selected." - (interactive) - (if (>= corfu--index 0) - (corfu--insert 'finished) - (corfu-quit))) - -;;;###autoload -(define-minor-mode corfu-mode - "COmpletion in Region FUnction." - :group 'corfu :keymap corfu-mode-map - (cond - (corfu-mode - (and corfu-auto (add-hook 'post-command-hook #'corfu--auto-post-command nil 'local)) - (setq-local completion-in-region-function #'corfu--in-region)) - (t - (remove-hook 'post-command-hook #'corfu--auto-post-command 'local) - (kill-local-variable 'completion-in-region-function)))) - -(defcustom global-corfu-modes t - "List of modes where Corfu should be enabled. -The variable can either be t, nil or a list of t, nil, mode -symbols or elements of the form (not modes). Examples: - - Enable everywhere, except in Org: ((not org-mode) t). - - Enable in programming modes except Python: ((not python-mode) prog-mode). - - Enable only in text modes: (text-mode)." - :type '(choice (const t) (repeat sexp))) - -;;;###autoload -(define-globalized-minor-mode global-corfu-mode - corfu-mode corfu--on - :group 'corfu) - -(defun corfu--on () - "Turn `corfu-mode' on." - (when (and (not (or noninteractive (eq (aref (buffer-name) 0) ?\s))) - ;; TODO backport `easy-mmode--globalized-predicate-p' - (or (eq t global-corfu-modes) - (eq t (cl-loop for p in global-corfu-modes thereis - (pcase-exhaustive p - ('t t) - ('nil 0) - ((pred symbolp) (and (derived-mode-p p) t)) - (`(not . ,m) (and (seq-some #'derived-mode-p m) 0))))))) - (corfu-mode 1))) - -;; Emacs 28: Do not show Corfu commands with M-X -(dolist (sym '(corfu-next corfu-previous corfu-first corfu-last corfu-quit corfu-reset - corfu-complete corfu-insert corfu-scroll-up corfu-scroll-down - corfu-insert-separator corfu-prompt-beginning corfu-prompt-end)) - (put sym 'completion-predicate #'ignore)) - -(defun corfu--capf-wrapper-advice (orig fun which) - "Around advice for `completion--capf-wrapper'. -The ORIG function takes the FUN and WHICH arguments." - (if corfu-mode (corfu--capf-wrapper fun t) (funcall orig fun which))) - -(defun corfu--eldoc-advice () - "Return non-nil if Corfu is currently not active." - (not (and corfu-mode completion-in-region-mode))) - -;; Install advice which fixes `completion--capf-wrapper', such that it respects -;; the completion styles for non-exclusive Capfs. See the fixme comment in the -;; `completion--capf-wrapper' function in minibuffer.el, where the issue has -;; been mentioned. -(advice-add #'completion--capf-wrapper :around #'corfu--capf-wrapper-advice) - -;; Register Corfu with ElDoc -(advice-add #'eldoc-display-message-no-interference-p - :before-while #'corfu--eldoc-advice) -(eldoc-add-command #'corfu-complete #'corfu-insert) - -(provide 'corfu) -;;; corfu.el ends here diff --git a/elpa/corfu-1.0/corfu.info b/elpa/corfu-1.0/corfu.info @@ -1,758 +0,0 @@ -This is docmcc15N.info, produced by makeinfo version 6.8 from -corfu.texi. - -INFO-DIR-SECTION Emacs misc features -START-INFO-DIR-ENTRY -* Corfu: (corfu). COmpletion in Region FUnction. -END-INFO-DIR-ENTRY - - -File: docmcc15N.info, Node: Top, Next: Features, Up: (dir) - -corfu.el - COmpletion in Region FUnction -**************************************** - -Corfu enhances in-buffer completion with a small completion popup. The -current candidates are shown in a popup below or above the point. The -candidates can be selected by moving up and down. Corfu is the -minimalistic in-buffer completion counterpart of the Vertico -(https://github.com/minad/vertico) minibuffer UI. - - Corfu is a small package, which relies on the Emacs completion -facilities and concentrates on providing a polished completion UI. -In-buffer completion UIs in Emacs can hook into ‘completion-in-region’, -which implements the interaction with the user. Completions at point -are either provided by commands like ‘dabbrev-completion’ or by -pluggable backends (‘completion-at-point-functions’, Capfs) and are then -passed to ‘completion-in-region’. Many programming, text and shell -major modes implement a Capf. Corfu does not include its own completion -backends. The Emacs built-in Capfs and the Capfs provided by -third-party programming language packages are often sufficient. -Additional Capfs and completion utilities are provided by the Cape -(https://github.com/minad/cape) package. - - *NOTE*: Corfu uses child frames to show the popup and falls back to -the default setting of the ‘completion-in-region-function’ on -non-graphical displays. If you want to use Corfu in the terminal, -install the package corfu-terminal -(https://codeberg.org/akib/emacs-corfu-terminal), which provides an -alternative overlay-based display. - -* Menu: - -* Features:: -* Installation and Configuration:: -* Key bindings:: -* Extensions:: -* Complementary packages:: -* Alternatives:: -* Debugging Corfu:: -* Contributions:: - -— The Detailed Node Listing — - -Installation and Configuration - -* Auto completion:: -* Completing in the minibuffer:: -* Completing in the Eshell or Shell:: -* Orderless completion:: -* TAB-only completion:: -* TAB-and-Go completion:: -* Transfer completion to the minibuffer:: - - - -File: docmcc15N.info, Node: Features, Next: Installation and Configuration, Prev: Top, Up: Top - -1 Features -********** - - • Timer-based auto-completions (_off_ by default, set ‘corfu-auto’). - • Popup display with scrollbar indicator and arrow key navigation. - • The popup can be summoned explicitly by pressing ‘TAB’ at any time. - • The current candidate is inserted with ‘TAB’ and selected with - ‘RET’. - • Candidate sorting by prefix, string length and alphabetically. - • The selected candidate is previewed (configurable via - ‘corfu-preview-current’). - • The selected candidate is automatically committed on further input - by default. (configurable via ‘corfu-preview-current’). - • Supports the Orderless (https://github.com/oantolin/orderless) - completion style. The filter string can contain arbitrary - characters, after inserting a space via ‘M-SPC’ (configurable via - ‘corfu-quit-at-boundary’ and ‘corfu-separator’). - • Lazy completion candidate highlighting for performance. - • Support for candidate annotations (‘annotation-function’, - ‘affixation-function’). - • Deprecated candidates are displayed as crossed out. - • Icons can be provided by an external package via margin formatter - functions. - • Rich set of extensions: Quick keys, Index keys, Sorting by history, - Candidate documentation in echo area, popup or separate buffer. - - -File: docmcc15N.info, Node: Installation and Configuration, Next: Key bindings, Prev: Features, Up: Top - -2 Installation and Configuration -******************************** - -Corfu is available from GNU ELPA -(https://elpa.gnu.org/packages/corfu.html), such that it can be -installed directly via ‘package-install’. After installation, the -global minor mode can be enabled with ‘M-x global-corfu-mode’. In order -to configure Corfu and other packages in your init.el, you may want to -use ‘use-package’. - - Corfu is highly flexible and customizable via ‘corfu-*’ customization -variables, such that you can adapt it precisely to your requirements. -However in order to quickly try out the Corfu completion package, it -should be sufficient to activate ‘global-corfu-mode’. You can -experiment with manual completion for example in an Elisp buffer or in -an Eshell or Shell buffer. For auto completion, set ‘corfu-auto’ to t -before turning on ‘global-corfu-mode’. - - Here is an example configuration: - - (use-package corfu - ;; Optional customizations - ;; :custom - ;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' - ;; (corfu-auto t) ;; Enable auto completion - ;; (corfu-separator ?\s) ;; Orderless field separator - ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary - ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match - ;; (corfu-preview-current nil) ;; Disable current candidate preview - ;; (corfu-preselect 'prompt) ;; Preselect the prompt - ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches - ;; (corfu-scroll-margin 5) ;; Use scroll margin - - ;; Enable Corfu only for certain modes. - ;; :hook ((prog-mode . corfu-mode) - ;; (shell-mode . corfu-mode) - ;; (eshell-mode . corfu-mode)) - - ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can - ;; be used globally (M-/). See also the customization variable - ;; `global-corfu-modes' to exclude certain modes. - :init - (global-corfu-mode)) - - ;; A few more useful configurations... - (use-package emacs - :init - ;; TAB cycle if there are only few candidates - (setq completion-cycle-threshold 3) - - ;; Emacs 28: Hide commands in M-x which do not apply to the current mode. - ;; Corfu commands are hidden, since they are not supposed to be used via M-x. - ;; (setq read-extended-command-predicate - ;; #'command-completion-default-include-p) - - ;; Enable indentation+completion using the TAB key. - ;; `completion-at-point' is often bound to M-TAB. - (setq tab-always-indent 'complete)) - - Dabbrev completion is based on ‘completion-in-region’ and can be used -with Corfu. You may want to swap the ‘dabbrev-completion’ with the -‘dabbrev-expand’ key for easier access, if you prefer completion. Also -take a look at the ‘cape-dabbrev’ completion at point function provided -by my Cape (https://github.com/minad/cape) package. - - ;; Use Dabbrev with Corfu! - (use-package dabbrev - ;; Swap M-/ and C-M-/ - :bind (("M-/" . dabbrev-completion) - ("C-M-/" . dabbrev-expand)) - ;; Other useful Dabbrev configurations. - :custom - (dabbrev-ignored-buffer-regexps '("\\.\\(?:pdf\\|jpe?g\\|png\\)\\'"))) - - If you start to configure the package more deeply, I recommend to -give the Orderless completion style a try for filtering. Orderless -completion is different from the familiar prefix TAB completion. Corfu -can be used with the default completion styles. The use of Orderless is -not a necessity. - - ;; Optionally use the `orderless' completion style. - (use-package orderless - :init - ;; Configure a custom style dispatcher (see the Consult wiki) - ;; (setq orderless-style-dispatchers '(+orderless-dispatch) - ;; orderless-component-separator #'orderless-escapable-split-on-space) - (setq completion-styles '(orderless basic) - completion-category-defaults nil - completion-category-overrides '((file (styles partial-completion))))) - - The ‘basic’ completion style is specified as fallback in addition to -‘orderless’ in order to ensure that completion commands which rely on -dynamic completion tables, e.g., ‘completion-table-dynamic’ or -‘completion-table-in-turn’, work correctly. See ‘+orderless-dispatch’ -in the Consult wiki (https://github.com/minad/consult/wiki) for an -advanced Orderless style dispatcher. Additionally enable -‘partial-completion’ for file path expansion. ‘partial-completion’ is -important for file wildcard support. Multiple files can be opened at -once with ‘find-file’ if you enter a wildcard. You may also give the -‘initials’ completion style a try. - - See also the Corfu Wiki (https://github.com/minad/corfu/wiki) and the -Cape manual (https://github.com/minad/cape) for additional Capf -configuration tips. For more general documentation read the chapter -about completion in the Emacs manual -(https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion.html). -If you want to create your own Capfs, you can find documentation about -completion in the Elisp manual -(https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion.html). - -* Menu: - -* Auto completion:: -* Completing in the minibuffer:: -* Completing in the Eshell or Shell:: -* Orderless completion:: -* TAB-only completion:: -* TAB-and-Go completion:: -* Transfer completion to the minibuffer:: - - -File: docmcc15N.info, Node: Auto completion, Next: Completing in the minibuffer, Up: Installation and Configuration - -2.1 Auto completion -=================== - -Auto completion is disabled by default, but can be enabled by setting -‘corfu-auto’ to t. Furthermore you may want to configure Corfu to quit -completion eagerly, such that the completion popup stays out of your way -when it appeared unexpectedly. - - ;; Enable auto completion and configure quitting - (setq corfu-auto t - corfu-quit-no-match 'separator) ;; or t - - I suggest to experiment with the various settings and key bindings to -find a configuration which works for you. There is no one perfect -configuration which fits all. Some people like auto completion, some -like manual completion, some want to cycle with TAB and some with the -arrow keys. - - In case you like auto completion settings, where the completion popup -appears immediately, better use a cheap completion style like ‘basic’, -which performs prefix filtering. In this case Corfu completion should -still be fast in buffers with efficient completion backends. You can -try the following settings in an Elisp buffer or the Emacs scratch -buffer. Note that such settings can slow down Emacs due to the high -load on the Lisp runtime and garbage collector. - - (setq-local corfu-auto t - corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED - corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED - completion-styles '(basic)) - - If you want to combine fast prefix filtering and Orderless filtering -you can still do that by defining a custom Orderless completion style -via ‘orderless-define-completion-style’. We use a custom style -dispatcher, which enables efficient prefix filtering for input shorter -than 4 characters. Note that such a setup is advanced. Please refer to -the Orderless documentation and source code for further details. - - (defun orderless-fast-dispatch (word index total) - (and (= index 0) (= total 1) (length< word 4) - `(orderless-regexp . ,(concat "^" (regexp-quote word))))) - - (orderless-define-completion-style orderless-fast - (orderless-style-dispatchers '(orderless-fast-dispatch)) - (orderless-matching-styles '(orderless-literal orderless-regexp))) - - (setq-local corfu-auto t - corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED - corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED - completion-styles '(orderless-fast basic)) - - -File: docmcc15N.info, Node: Completing in the minibuffer, Next: Completing in the Eshell or Shell, Prev: Auto completion, Up: Installation and Configuration - -2.2 Completing in the minibuffer -================================ - -Corfu can be used for completion in the minibuffer, since it relies on -child frames to display the candidates. By default, ‘global-corfu-mode’ -does not activate ‘corfu-mode’ in the minibuffer, to avoid interference -with specialised minibuffer completion UIs like Vertico or Mct. However -you may still want to enable Corfu completion for commands like ‘M-:’ -(‘eval-expression’) or ‘M-!’ (‘shell-command’), which read from the -minibuffer. Activate ‘corfu-mode’ only if ‘completion-at-point’ is -bound in the minibuffer-local keymap to achieve this effect. - - (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-auto nil) ;; Enable/disable auto completion - (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) - - You can also enable Corfu more generally for every minibuffer, as -long as no completion UI is active. In the following example we check -for Mct and Vertico. Furthermore we ensure that Corfu is not enabled if -a password is read from the minibuffer. - - (defun corfu-enable-always-in-minibuffer () - "Enable Corfu in the minibuffer if Vertico/Mct are not active." - (unless (or (bound-and-true-p mct--active) - (bound-and-true-p vertico--input) - (eq (current-local-map) read-passwd-map)) - ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion - (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-always-in-minibuffer 1) - - -File: docmcc15N.info, Node: Completing in the Eshell or Shell, Next: Orderless completion, Prev: Completing in the minibuffer, Up: Installation and Configuration - -2.3 Completing in the Eshell or Shell -===================================== - -When completing in the Eshell I recommend conservative local settings -without auto completion, such that the completion behavior is similar to -widely used shells like Bash, Zsh or Fish. - - (add-hook 'eshell-mode-hook - (lambda () - (setq-local corfu-auto nil) - (corfu-mode))) - - When pressing ‘RET’ while the Corfu popup is visible, the -‘corfu-insert’ command will be invoked. This command does inserts the -currently selected candidate, but it does not send the prompt input to -Eshell or the Comint process. Therefore you often have to press ‘RET’ -twice which feels like an unnecessary double confirmation. Fortunately -it is easy to improve this! In my configuration I define the advice -‘corfu-send-shell’ which sends the candidate after insertion. - - (defun corfu-send-shell (&rest _) - "Send completion candidate when inside comint/eshell." - (cond - ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) - (eshell-send-input)) - ((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) - (comint-send-input)))) - - (advice-add #'corfu-insert :after #'corfu-send-shell) - - Shell completion uses the flexible Pcomplete mechanism internally, -which allows you to program the completions per shell command. If you -want to know more, look into this blog post -(https://www.masteringemacs.org/article/pcomplete-context-sensitive-completion-emacs), -which shows how to configure Pcomplete for git commands. - - You can try the pcmpl-args -(https://github.com/JonWaltman/pcmpl-args.el) package which extends -Pcomplete with completion support and helpful annotation support for -more commands. Similar to the Fish shell, ‘pcmpl-args’ uses man page -parsing and ‘--help’ output parsing to dynamically generate completions. -Since Emacs 29, Pcomplete offers the ‘pcomplete-from-help’ function -which parses the ‘--help’ output of a command and produces completions. -This Emacs 29 functionality is not completely equivalent. For example -it does not display annotations in Eshell, but this may get fixed in -Emacs 30. - - Pcomplete has a few bugs on Emacs 28 and older. We can work around -the issues with the Cape (https://github.com/minad/cape) library -(Completion at point extensions). Cape provides wrappers which sanitize -the Pcomplete function. If you use Emacs 28 or older installing these -advices is recommended such that Pcomplete works properly. On Emacs 29 -the advices should not be necessary anymore, since most of the relevant -bugs have been fixed. I therefore recommend to remove the advices on -Emacs 29 and eventually report any remaining Pcomplete issues upstream, -such that they can be fixed. - - ;; The advices are only needed on Emacs 28 and older. - (when (< emacs-major-version 29) - ;; Silence the pcomplete capf, no errors or messages! - (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent) - - ;; Ensure that pcomplete does not write to the buffer - ;; and behaves as a pure `completion-at-point-function'. - (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)) - - -File: docmcc15N.info, Node: Orderless completion, Next: TAB-only completion, Prev: Completing in the Eshell or Shell, Up: Installation and Configuration - -2.4 Orderless completion -======================== - -Orderless (https://github.com/oantolin/orderless) is an advanced -completion style that supports multi-component search filters separated -by a configurable character (space, by default). Normally, entering -characters like space which lie outside the completion region boundaries -(words, typically) causes Corfu to quit. This behavior is helpful with -auto-completion, which may pop-up when not desired, e.g. on entering a -new variable name. Just keep typing and Corfu will get out of the way. - - But orderless search terms can contain arbitrary characters; they are -also interpreted as regular expressions. To use orderless, set -‘corfu-separator’ (a space, by default) to the primary character of your -orderless component separator. - - Then, when a new orderless component is desired, use ‘M-SPC’ -(‘corfu-insert-separator’) to enter the first component separator in the -input, and arbitrary orderless search terms and new separators can be -entered thereafter. - - To treat the entire input as Orderless input, you can set the -customization option ‘corfu-quit-at-boundary’ to nil. This disables the -predicate which checks if the current completion boundary has been left. -In contrast, if you always want to quit at the boundary, set -‘corfu-quit-at-boundary’ to t. By default ‘corfu-quit-at-boundary’ is -set to ‘separator’ which quits at completion boundaries as long as no -separator has been inserted with ‘corfu-insert-separator’. - - Finally, there exists the user option ‘corfu-quit-no-match’ which is -set to ‘separator’ by default. With this setting Corfu stays alive as -soon as you start advanced filtering with a ‘corfu-separator’ even if -there are no matches, for example due to a typo. As long as no -separator character has been inserted with ‘corfu-insert-separator’, -Corfu will still quit if there are no matches. This ensures that the -Corfu popup goes away quickly if completion is not possible. - - In the following we show two configurations, one which works best -with auto completion and one which may work better with manual -completion if you prefer to always use ‘SPC’ to separate the Orderless -components. - - ;; Auto completion example - (use-package corfu - :custom - (corfu-auto t) ;; Enable auto completion - ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space - :bind - ;; Another key binding can be used, such as S-SPC. - ;; (:map corfu-map ("M-SPC" . corfu-insert-separator)) - :init - (global-corfu-mode)) - - ;; Manual completion example - (use-package corfu - :custom - ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space - :bind - ;; Configure SPC for separator insertion - (:map corfu-map ("SPC" . corfu-insert-separator)) - :init - (global-corfu-mode)) - - -File: docmcc15N.info, Node: TAB-only completion, Next: TAB-and-Go completion, Prev: Orderless completion, Up: Installation and Configuration - -2.5 TAB-only completion -======================= - -By default, Corfu steals both the ‘RET’ and ‘TAB’ keys, when the Corfu -popup is open. This can feel intrusive, in particular in combination -with auto completion. ‘RET’ may accidentally commit an automatically -selected candidate, while you actually wanted to start a new line. As -an alternative we can unbind the ‘RET’ key completely from ‘corfu-map’ -or reserve the ‘RET’ key only in shell modes. - - ;; TAB-only configuration - (use-package corfu - :custom - (corfu-auto t) ;; Enable auto completion - (corfu-preselect 'directory) ;; Select the first candidate, except for directories - - ;; Free the RET key for less intrusive behavior. - :bind - (:map corfu-map - ;; Option 1: Unbind RET completely - ;;; ("RET" . nil) - ;; Option 2: Use RET only in shell modes - ("RET" . (menu-item "" nil :filter corfu-insert-shell-filter))) - - :init - (global-corfu-mode)) - - (defun corfu-insert-shell-filter (&optional _) - "Insert completion candidate and send when inside comint/eshell." - (when (or (derived-mode-p 'eshell-mode) (derived-mode-p 'comint-mode)) - (lambda () - (interactive) - (corfu-insert) - ;; `corfu-send-shell' was defined above - (corfu-send-shell)))) - - -File: docmcc15N.info, Node: TAB-and-Go completion, Next: Transfer completion to the minibuffer, Prev: TAB-only completion, Up: Installation and Configuration - -2.6 TAB-and-Go completion -========================= - -You may be interested in configuring Corfu in TAB-and-Go style. -Pressing TAB moves to the next candidate and further input will then -commit the selection. Note that further input will not expand snippets -or templates, which may not be desired but which leads overall to a more -predictable behavior. In order to force snippet expansion, confirm a -candidate explicitly with ‘RET’. - - (use-package corfu - ;; TAB-and-Go customizations - :custom - (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' - (corfu-preselect 'prompt) ;; Always preselect the prompt - - ;; Use TAB for cycling, default is `corfu-complete'. - :bind - (:map corfu-map - ("TAB" . corfu-next) - ([tab] . corfu-next) - ("S-TAB" . corfu-previous) - ([backtab] . corfu-previous)) - - :init - (global-corfu-mode)) - - -File: docmcc15N.info, Node: Transfer completion to the minibuffer, Prev: TAB-and-Go completion, Up: Installation and Configuration - -2.7 Transfer completion to the minibuffer -========================================= - -Sometimes it is useful to transfer the Corfu completion session to the -minibuffer, since the minibuffer offers richer interaction features. In -particular, Embark (https://github.com/oantolin/embark) is available in -the minibuffer, such that you can act on the candidates or -export/collect the candidates to a separate buffer. We could add Corfu -support to Embark in the future, such that export/collect is possible -directly from Corfu. But in my opinion having the ability to transfer -the Corfu completion to the minibuffer is an even better feature, since -further completion can be performed there. - - The command ‘corfu-move-to-minibuffer’ is defined here in terms of -‘consult-completion-in-region’, which uses the minibuffer completion UI -via ‘completing-read’. - - (defun corfu-move-to-minibuffer () - (interactive) - (when completion-in-region--data - (let ((completion-extra-properties corfu--extra) - completion-cycle-threshold completion-cycling) - (apply #'consult-completion-in-region completion-in-region--data)))) - (keymap-set corfu-map "M-m" #'corfu-move-to-minibuffer) - (add-to-list 'corfu-continue-commands #'corfu-move-to-minibuffer) - - -File: docmcc15N.info, Node: Key bindings, Next: Extensions, Prev: Installation and Configuration, Up: Top - -3 Key bindings -************** - -Corfu uses a transient keymap ‘corfu-map’ which is active while the -popup is shown. The keymap defines the following remappings and -bindings: - - • ‘move-beginning-of-line’ -> ‘corfu-prompt-beginning’ - • ‘move-end-of-line’ -> ‘corfu-prompt-end’ - • ‘beginning-of-buffer’ -> ‘corfu-first’ - • ‘end-of-buffer’ -> ‘corfu-last’ - • ‘scroll-down-command’ -> ‘corfu-scroll-down’ - • ‘scroll-up-command’ -> ‘corfu-scroll-up’ - • ‘next-line’, ‘down’, ‘M-n’ -> ‘corfu-next’ - • ‘previous-line’, ‘up’, ‘M-p’ -> ‘corfu-previous’ - • ‘completion-at-point’, ‘TAB’ -> ‘corfu-complete’ - • ‘RET’ -> ‘corfu-insert’ - • ‘M-g’ -> ‘corfu-info-location’ - • ‘M-h’ -> ‘corfu-info-documentation’ - • ‘M-SPC’ -> ‘corfu-insert-separator’ - • ‘C-g’ -> ‘corfu-quit’ - • ‘keyboard-escape-quit’ -> ‘corfu-reset’ - - -File: docmcc15N.info, Node: Extensions, Next: Complementary packages, Prev: Key bindings, Up: Top - -4 Extensions -************ - -We maintain small extension packages to Corfu in this repository in the -subdirectory extensions/ -(https://github.com/minad/corfu/tree/main/extensions). The extensions -are installed together with Corfu if you pull the package from ELPA. -The extensions are inactive by default and can be enabled manually if -desired. Furthermore it is possible to install all of the files -separately, both ‘corfu.el’ and the ‘corfu-*.el’ extensions. Currently -the following extensions come with the Corfu ELPA package: - - • corfu-echo - (https://github.com/minad/corfu/blob/main/extensions/corfu-echo.el): - ‘corfu-echo-mode’ displays a brief candidate documentation in the - echo area. - • corfu-history - (https://github.com/minad/corfu/blob/main/extensions/corfu-history.el): - ‘corfu-history-mode’ remembers selected candidates and sorts the - candidates by their history position. - • corfu-indexed - (https://github.com/minad/corfu/blob/main/extensions/corfu-indexed.el): - ‘corfu-indexed-mode’ allows you to select indexed candidates with - prefix arguments. - • corfu-info - (https://github.com/minad/corfu/blob/main/extensions/corfu-info.el): - Actions to access the candidate location and documentation. - • corfu-popupinfo - (https://github.com/minad/corfu/blob/main/extensions/corfu-popupinfo.el): - Display candidate documentation or source in a popup next to the - candidate menu. - • corfu-quick - (https://github.com/minad/corfu/blob/main/extensions/corfu-quick.el): - Commands to select using Avy-style quick keys. - - See the Commentary of those files for configuration details. - - -File: docmcc15N.info, Node: Complementary packages, Next: Alternatives, Prev: Extensions, Up: Top - -5 Complementary packages -************************ - -Corfu works well together with all packages providing code completion -via the ‘completion-at-point-functions’. Many modes and packages -already provide a Capf out of the box. Nevertheless you may want to -look into complementary packages to enhance your setup. - - • corfu-terminal (https://codeberg.org/akib/emacs-corfu-terminal): - The corfu-terminal package provides an overlay-based display for - Corfu, such that you can use Corfu in terminal Emacs. - - • corfu-candidate-overlay - (https://code.bsdgeek.org/adam/corfu-candidate-overlay): Shows - as-you-type auto-suggestion candidate overlay with a visual - indication of whether there are many or exactly one candidate - available (works only with ‘corfu-auto’ disabled). - - • Orderless (https://github.com/oantolin/orderless): Corfu supports - completion styles, including the advanced ‘orderless’ completion - style, where the filter expressions are separated by spaces or - another character (see ‘corfu-separator’). - - • Cape (https://github.com/minad/cape): Provides additional Capf - backends and ‘completion-in-region’ commands. Among others, the - package supplies the file completion backend ‘cape-file’ and the - Dabbrev backend ‘cape-dabbrev’. Cape provides the - ‘cape-company-to-capf’ adapter to reuse Company backends in Corfu. - - • nerd-icons-corfu (https://github.com/LuigiPiucco/nerd-icons-corfu), - kind-icon (https://github.com/jdtsmith/kind-icon): Icons are - supported by Corfu via external packages. The nerd-icons-corfu - package relies on the Nerd icon font, which is even supported on - terminal, while kind-icon uses SVGs from monochromatic icon sets. - - • pcmpl-args (https://github.com/JonWaltman/pcmpl-args.el): Extend - the Eshell/Shell Pcomplete mechanism with support for many - commands. Similar to the Fish shell, pcmpl-args uses man page - parsing to dynamically retrieve the completions and helpful - annotations. - - • Tempel (https://github.com/minad/tempel): Tiny template/snippet - package with templates in Lisp syntax, which can be used in - conjunction with Corfu. - - • Vertico (https://github.com/minad/vertico): You may also want to - look into my Vertico package. Vertico is the minibuffer completion - counterpart of Corfu. - - -File: docmcc15N.info, Node: Alternatives, Next: Debugging Corfu, Prev: Complementary packages, Up: Top - -6 Alternatives -************** - - • Company (https://github.com/company-mode/company-mode): Company is - a widely used and mature completion package, which implements a - similar UI as Corfu. While Corfu relies exclusively on the - standard Emacs completion API (Capfs), Company defines its own API - for the backends. Company includes its own completion backends, - following its own API, which are incompatible with the Emacs - completion infrastructure. Company provides an adapter - ‘company-capf’ to handle Capfs as a Company backend. As a result - of this design, Company is a more complex package than Corfu. - Company by default uses overlays for the popup in contrast to the - child frames used by Corfu. Overall both packages work well, but - Company integrates less tightly with Emacs. The - ‘completion-styles’ support is more limited and the - ‘completion-at-point’ command and the ‘completion-in-region’ - function do not invoke Company. - - • consult-completion-in-region (https://github.com/minad/consult): - The Consult package provides the function - ‘consult-completion-in-region’ which can be set as - ‘completion-in-region-function’ such that it handles - ‘completion-at-point’. The function works by transferring the - in-buffer completion to the minibuffer. In the minibuffer, the - minibuffer completion UI, for example Vertico - (https://github.com/minad/vertico) takes over. If you prefer to - perform all your completions in the minibuffer - ‘consult-completion-in-region’ is your best option. - - -File: docmcc15N.info, Node: Debugging Corfu, Next: Contributions, Prev: Alternatives, Up: Top - -7 Debugging Corfu -***************** - -When you observe an error in the ‘corfu--post-command’ post command -hook, you should install an advice to enforce debugging. This allows -you to obtain a stack trace in order to narrow down the location of the -error. The reason is that post command hooks are automatically disabled -(and not debugged) by Emacs. Otherwise Emacs would become unusable, -given that the hooks are executed after every command. - - (setq debug-on-error t) - - (defun force-debug (func &rest args) - (condition-case e - (apply func args) - ((debug error) (signal (car e) (cdr e))))) - - (advice-add #'corfu--post-command :around #'force-debug) - - When Capfs do not yield the expected result you can use -‘cape-capf-debug’ to add debug messages to a Capf. The Capf will then -produce a completion log in the messages buffer. - - (setq completion-at-point-functions (list (cape-capf-debug #'cape-dict))) - - -File: docmcc15N.info, Node: Contributions, Prev: Debugging Corfu, Up: Top - -8 Contributions -*************** - -Since this package is part of GNU ELPA -(https://elpa.gnu.org/packages/corfu.html) contributions require a -copyright assignment to the FSF. - - - -Tag Table: -Node: Top208 -Node: Features2271 -Node: Installation and Configuration3750 -Node: Auto completion9432 -Node: Completing in the minibuffer11989 -Node: Completing in the Eshell or Shell14145 -Node: Orderless completion17582 -Node: TAB-only completion20676 -Node: TAB-and-Go completion22224 -Node: Transfer completion to the minibuffer23335 -Node: Key bindings24773 -Node: Extensions25892 -Node: Complementary packages27692 -Node: Alternatives30210 -Node: Debugging Corfu31956 -Node: Contributions33012 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/corfu-1.3.signed b/elpa/corfu-1.3.signed @@ -0,0 +1,2 @@ +Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2024-04-05T11:05:05+0200 using RSA +Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) <elpasign@elpa.gnu.org> (trust undefined) created at 2024-04-05T11:05:05+0200 using EDDSA +\ No newline at end of file diff --git a/elpa/corfu-1.3/CHANGELOG.org b/elpa/corfu-1.3/CHANGELOG.org @@ -0,0 +1,112 @@ +#+title: corfu.el - Changelog +#+author: Daniel Mendler +#+language: en + +* Version 1.3 (2024-04-05) + +- Preserve currently selected candidate on further input. This matters if + candidate preview is disabled (~corfu-preview-current=nil~). +- Add new command ~corfu-expand~ bound to ~M-TAB~ by default. The command expands + the input via ~completion-try-completion~, for example the ~basic~ completion + style expands the common prefix of all candidates. + +* Version 1.2 (2024-01-23) + +- Support the EXWM window manager. +- Optimization: Reduce auto completion timer overhead. +- Use ~internal-border-width~ instead of ~child-frame-border-width~. +- Internal refactoring: Do not use buffer-local variables. +- Internal refactoring: Store ~completion-extra-properties~ as part of + ~completion-in-region--data~. + +* Version 1.1 (2023-12-27) + +- Deduplicate candidates with respect to ~equal-including-properties~, such that + backends can provide equal candidate strings, which only differ in their text + properties and annotations. +- Ensure that the string passed to the ~:exit-function~ retains the candidate + properties, when possible. The properties are guaranteed to exist when a + candidate is selected explicitly, but may be missing when candidates are + completed in a stepwise manner. +- ~corfu-on-exact-match~: Add value ~show~ to the customization option. With this + setting the Corfu popup will be shown even if there is only a single matching + candidate. + +* Version 1.0 (2023-12-01) + +- Bug fixes. +- =corfu-quick=: Use a slightly different scheme to support more candidates. +- =corfu-reset=: Quit immediately if input did not change. +- Support =completion-lazy-hilit=. + +* Version 0.38 (2023-08-14) + +- =corfu-quick=: Bugfix. +- =corfu-mode-map=: Add mode map. +- Replace =corfu-excluded-modes= with =global-corfu-modes=, the Emacs 28 convention + for globalized minor modes. + +* Version 0.37 (2023-07-02) + +- Bugfixes. +- Improve child frame display code, =corfu--popup-show= takes a =posn= argument. +- Ensure that the popup font matches the font of the parent frame. +- Close popup when window selection changes. +- Remove =corfu-history-length=. Instead set the =history-length= property of + =corfu-history= variable. +- =corfu-info-documentation=, =corfu-info-location=: Make buffer and window + persistent if called with prefix argument. + +* Version 0.36 (2023-03-27) + +- Drop obsolete =corfu-preselect-first=. +- =corfu-popupinfo-delay= and =corfu-echo-delay=: Remove support for value =t=. + Instant updates are not recommended. It is still possible to use a small value + for the delay. +- Rename =corfu-excluded-modes= to =corfu-exclude-modes= (Naming convention). +- Remove call to =undo-boundary=, which caused issues with auto completion. + +* Version 0.35 (2023-02-17) + +- =corfu-popupinfo=: Take more text into account when computing popup width. +- =corfu-popupinfo=: Change keybindings, remap =corfu-info-documentation/location=. +- =corfu-popupinfo=: Add commands =corfu-popupinfo-beginning/end=. +- =corfu-popupinfo=: Improve popup placement. +- Add =corfu-prompt-beginning= and =corfu-prompt-end= commands. +- Add =corfu-preselect= option, deprecate =corfu-preselect-first=. +- Use =cl-defgeneric= internally as mechanism to allow extensions to override + functionality, e.g., the candidate formatting and display. + +* Version 0.34 (2022-12-03) + +- Bugfixes +- Popup frame code updated for Emacs 29. Please report any issues. +- =corfu-popupinfo-direction=: Variable must be a list of directions. +- Support height adjustments of =corfu-default= face + +* Version 0.33 (2022-11-21) + +- =corfu-popupinfo=: Bugfixes + +* Version 0.31 (2022-11-20) + +- =corfu-echo=, =corfu-quick=: Bugfixes for interaction issue. + +* Version 0.30 (2022-11-19) + +- =corfu-popupinfo=: Bugfixes and improvements. + +* Version 0.29 (2022-11-19) + +- BREAKING: Extract the =corfu-echo= extension from =corfu.el=. In order to see echo + messages, enable =corfu-echo-mode=. You probably want to enable either + =corfu-echo-mode= or =corfu-popupinfo-mode=. +- BREAKING: Rename =corfu-echo-documentation= to =corfu-echo-delay=. +- Add =corfu-popupinfo= extension to display candidate documentation and location + in a small child frame next to the candidate menu. This extension has been + contributed by Yuwei Tian who assigned copyright to the FSF. The extension + supersedes Yuwei's =corfu-doc= package. + +* Version 0.28 (2022-10-16) + +- Start of changelog. diff --git a/elpa/corfu-1.3/README-elpa b/elpa/corfu-1.3/README-elpa @@ -0,0 +1,804 @@ + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + CORFU.EL - COMPLETION IN REGION FUNCTION + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + +Corfu enhances in-buffer completion with a small completion popup. The +current candidates are shown in a popup below or above the point. The +candidates can be selected by moving up and down. Corfu is the +minimalistic in-buffer completion counterpart of the [Vertico] +minibuffer UI. + +Corfu is a small package, which relies on the Emacs completion +facilities and concentrates on providing a polished completion +UI. In-buffer completion UIs in Emacs can hook into +`completion-in-region', which implements the interaction with the +user. Completions at point are either provided by commands like +`dabbrev-completion' or by pluggable backends +(`completion-at-point-functions', Capfs) and are then passed to +`completion-in-region'. Many programming, text and shell major modes +implement a Capf. Corfu does not include its own completion +backends. The Emacs built-in Capfs and the Capfs provided by third-party +programming language packages are often sufficient. Additional Capfs and +completion utilities are provided by the [Cape] package. + +*NOTE*: Corfu uses child frames to show the popup and falls back to the +default setting of the `completion-in-region-function' on non-graphical +displays. If you want to use Corfu in the terminal, install the package +[corfu-terminal], which provides an alternative overlay-based display. + +Table of Contents +───────────────── + +1. Features +2. Installation +3. Key bindings +4. Configuration +.. 1. Auto completion +.. 2. Completing in the minibuffer +.. 3. Completing in the Eshell or Shell +.. 4. Orderless completion +.. 5. TAB-only completion +.. 6. TAB-and-Go completion +.. 7. Expanding to the common candidate prefix with TAB +.. 8. Transfer completion to the minibuffer +5. Extensions +6. Complementary packages +7. Alternatives +8. Debugging Corfu +9. Contributions + + +[Vertico] <https://github.com/minad/vertico> + +[Cape] <https://github.com/minad/cape> + +[corfu-terminal] <https://codeberg.org/akib/emacs-corfu-terminal> + + +1 Features +══════════ + + • Timer-based auto-completions (/off/ by default, set `corfu-auto'). + • Popup display with scrollbar indicator and arrow key navigation. + • The popup can be summoned explicitly by pressing `TAB' at any time. + • The current candidate is inserted with `TAB' and selected with + `RET'. + • Candidate sorting by prefix, string length and alphabetically. + • The selected candidate is previewed (configurable via + `corfu-preview-current'). + • The selected candidate is automatically committed on further input + by default. (configurable via `corfu-preview-current'). + • Supports the [Orderless] completion style. The filter string can + contain arbitrary characters, after inserting a space via `M-SPC' + (configurable via `corfu-quit-at-boundary' and `corfu-separator'). + • Lazy completion candidate highlighting for performance. + • Support for candidate annotations (`annotation-function', + `affixation-function'). + • Deprecated candidates are displayed as crossed out. + • Icons can be provided by an external package via margin formatter + functions. + • Rich set of extensions: Quick keys, Index keys, Sorting by history, + Candidate documentation in echo area, popup or separate buffer. + + +[Orderless] <https://github.com/oantolin/orderless> + + +2 Installation +══════════════ + + Corfu is available from [GNU ELPA]. You can install it directly via + `M-x package-install RET corfu RET'. After installation, activate the + global minor mode with `M-x global-corfu-mode RET'. Set the variable + `corfu-auto' to t in order to enable auto completion. For manual + completion press `M-TAB' (or `TAB') within a buffer. + + +[GNU ELPA] <https://elpa.gnu.org/packages/corfu.html> + + +3 Key bindings +══════════════ + + Corfu uses a transient keymap `corfu-map' which is active while the + popup is shown. The keymap defines the following remappings of + fundamental commands and bindings: + + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + Binding/Remapping Corfu command + ────────────────────────────────────────────────────────── + `move-beginning-of-line' `corfu-prompt-beginning' + `move-end-of-line' `corfu-prompt-end' + `beginning-of-buffer' `corfu-first' + `end-of-buffer' `corfu-last' + `scroll-down-command' `corfu-scroll-down' + `scroll-up-command' `corfu-scroll-up' + `next-line', `down', `M-n' `corfu-next' + `previous-line', `up', `M-p' `corfu-previous' + `completion-at-point', `TAB' `corfu-complete' + `M-TAB' `corfu-expand' + `RET' `corfu-insert' + `M-g' `corfu-info-location' + `M-h' `corfu-info-documentation' + `M-SPC' `corfu-insert-separator' + `C-g' `corfu-quit' + `keyboard-escape-quit' `corfu-reset' + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + +4 Configuration +═══════════════ + + In order to configure Corfu and other packages in your init.el, you + may want to use `use-package'. Corfu is flexibly customizable via + `corfu-*' customization variables, such that you can adapt it + precisely to your requirements. However in order to quickly try out + the Corfu completion package, it should be sufficient to activate + `global-corfu-mode'. You can experiment with manual completion for + example in an Elisp buffer or in an Eshell or Shell buffer. For auto + completion, set `corfu-auto' to t before turning on + `global-corfu-mode'. + + Here is an example configuration: + + ┌──── + │ (use-package corfu + │ ;; Optional customizations + │ ;; :custom + │ ;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' + │ ;; (corfu-auto t) ;; Enable auto completion + │ ;; (corfu-separator ?\s) ;; Orderless field separator + │ ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary + │ ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match + │ ;; (corfu-preview-current nil) ;; Disable current candidate preview + │ ;; (corfu-preselect 'prompt) ;; Preselect the prompt + │ ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches + │ ;; (corfu-scroll-margin 5) ;; Use scroll margin + │ + │ ;; Enable Corfu only for certain modes. + │ ;; :hook ((prog-mode . corfu-mode) + │ ;; (shell-mode . corfu-mode) + │ ;; (eshell-mode . corfu-mode)) + │ + │ ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can + │ ;; be used globally (M-/). See also the customization variable + │ ;; `global-corfu-modes' to exclude certain modes. + │ :init + │ (global-corfu-mode)) + │ + │ ;; A few more useful configurations... + │ (use-package emacs + │ :init + │ ;; TAB cycle if there are only few candidates + │ ;; (setq completion-cycle-threshold 3) + │ + │ ;; Enable indentation+completion using the TAB key. + │ ;; `completion-at-point' is often bound to M-TAB. + │ (setq tab-always-indent 'complete) + │ + │ ;; Emacs 30 and newer: Disable Ispell completion function. As an alternative, + │ ;; try `cape-dict'. + │ (setq text-mode-ispell-word-completion nil) + │ + │ ;; Emacs 28 and newer: Hide commands in M-x which do not apply to the current + │ ;; mode. Corfu commands are hidden, since they are not used via M-x. This + │ ;; setting is useful beyond Corfu. + │ (setq read-extended-command-predicate #'command-completion-default-include-p)) + └──── + + Dabbrev completion is based on `completion-in-region' and can be used + with Corfu. You may want to swap the `dabbrev-completion' with the + `dabbrev-expand' key for easier access, if you prefer completion. Also + take a look at the `cape-dabbrev' completion at point function + provided by my [Cape] package. + + ┌──── + │ ;; Use Dabbrev with Corfu! + │ (use-package dabbrev + │ ;; Swap M-/ and C-M-/ + │ :bind (("M-/" . dabbrev-completion) + │ ("C-M-/" . dabbrev-expand)) + │ :config + │ (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ") + │ ;; Since 29.1, use `dabbrev-ignored-buffer-regexps' on older. + │ (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode) + │ (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode)) + └──── + + If you start to configure the package more deeply, I recommend to give + the Orderless completion style a try for filtering. Orderless + completion is different from the familiar prefix TAB completion. Corfu + can be used with the default completion styles. The use of Orderless + is not a necessity. + + ┌──── + │ ;; Optionally use the `orderless' completion style. + │ (use-package orderless + │ :init + │ ;; Configure a custom style dispatcher (see the Consult wiki) + │ ;; (setq orderless-style-dispatchers '(+orderless-dispatch) + │ ;; orderless-component-separator #'orderless-escapable-split-on-space) + │ (setq completion-styles '(orderless basic) + │ completion-category-defaults nil + │ completion-category-overrides '((file (styles partial-completion))))) + └──── + + The `basic' completion style is specified as fallback in addition to + `orderless' in order to ensure that completion commands which rely on + dynamic completion tables, e.g., `completion-table-dynamic' or + `completion-table-in-turn', work correctly. See `+orderless-dispatch' + in the [Consult wiki] for an advanced Orderless style + dispatcher. Additionally enable `partial-completion' for file path + expansion. `partial-completion' is important for file wildcard + support. Multiple files can be opened at once with `find-file' if you + enter a wildcard. You may also give the `initials' completion style a + try. + + See also the [Corfu Wiki] and the [Cape manual] for additional Capf + configuration tips. For more general documentation read the chapter + about completion in the [Emacs manual]. If you want to create your own + Capfs, you can find documentation about completion in the [Elisp + manual]. + + +[Cape] <https://github.com/minad/cape> + +[Consult wiki] <https://github.com/minad/consult/wiki> + +[Corfu Wiki] <https://github.com/minad/corfu/wiki> + +[Cape manual] <https://github.com/minad/cape> + +[Emacs manual] +<https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion.html> + +[Elisp manual] +<https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion.html> + +4.1 Auto completion +─────────────────── + + Auto completion is disabled by default, but can be enabled by setting + `corfu-auto' to t. Furthermore you may want to configure Corfu to quit + completion eagerly, such that the completion popup stays out of your + way when it appeared unexpectedly. + + ┌──── + │ ;; Enable auto completion and configure quitting + │ (setq corfu-auto t + │ corfu-quit-no-match 'separator) ;; or t + └──── + + I suggest to experiment with the various settings and key bindings to + find a configuration which works for you. There is no one perfect + configuration which fits all. Some people like auto completion, some + like manual completion, some want to cycle with TAB and some with the + arrow keys. + + In case you like auto completion settings, where the completion popup + appears immediately, better use a cheap completion style like `basic', + which performs prefix filtering. In this case Corfu completion should + still be fast in buffers with efficient completion backends. You can + try the following settings in an Elisp buffer or the Emacs scratch + buffer. Note that such settings can slow down Emacs due to the high + load on the Lisp runtime and garbage collector. + + ┌──── + │ (setq-local corfu-auto t + │ corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED + │ corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED + │ completion-styles '(basic)) + └──── + + If you want to combine fast prefix filtering and Orderless filtering + you can still do that by defining a custom Orderless completion style + via `orderless-define-completion-style'. We use a custom style + dispatcher, which enables efficient prefix filtering for input shorter + than 4 characters. Note that such a setup is advanced. Please refer to + the Orderless documentation and source code for further details. + + ┌──── + │ (defun orderless-fast-dispatch (word index total) + │ (and (= index 0) (= total 1) (length< word 4) + │ (cons 'orderless-literal-prefix word)))) + │ + │ (orderless-define-completion-style orderless-fast + │ (orderless-style-dispatchers '(orderless-fast-dispatch)) + │ (orderless-matching-styles '(orderless-literal orderless-regexp))) + │ + │ (setq-local corfu-auto t + │ corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED + │ corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED + │ completion-styles '(orderless-fast basic)) + └──── + + +4.2 Completing in the minibuffer +──────────────────────────────── + + Corfu can be used for completion in the minibuffer, since it relies on + child frames to display the candidates. The Corfu popup can be shown + even if it doesn't fully fit inside the minibuffer. + + By default, `global-corfu-mode' does not activate `corfu-mode' in the + minibuffer, to avoid interference with specialised minibuffer + completion UIs like Vertico or Mct. However you may still want to + enable Corfu completion for commands like `M-:' (`eval-expression') or + `M-!' (`shell-command'), which read from the minibuffer. In order to + detect minibuffers with completion we check if the variable + `completion-at-point-functions' is set locally. + + ┌──── + │ (defun corfu-enable-in-minibuffer () + │ "Enable Corfu in the minibuffer." + │ (when (local-variable-p 'completion-at-point-functions) + │ ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion + │ (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) + └──── + + This is not recommended, but one can also enable Corfu more generally + for every minibuffer, as long as no completion UI is active. In the + following example we check for Mct and Vertico. Furthermore we ensure + that Corfu is not enabled if a password is read from the minibuffer. + + ┌──── + │ (defun corfu-enable-always-in-minibuffer () + │ "Enable Corfu in the minibuffer if Vertico/Mct are not active." + │ (unless (or (bound-and-true-p mct--active) + │ (bound-and-true-p vertico--input) + │ (eq (current-local-map) read-passwd-map)) + │ ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion + │ (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-always-in-minibuffer 1) + └──── + + +4.3 Completing in the Eshell or Shell +───────────────────────────────────── + + When completing in the Eshell I recommend conservative local settings + without auto completion, such that the completion behavior is similar + to widely used shells like Bash, Zsh or Fish. + + ┌──── + │ (add-hook 'eshell-mode-hook + │ (lambda () + │ (setq-local corfu-auto nil) + │ (corfu-mode))) + └──── + + When pressing `RET' while the Corfu popup is visible, the + `corfu-insert' command will be invoked. This command does inserts the + currently selected candidate, but it does not send the prompt input to + Eshell or the Comint process. Therefore you often have to press `RET' + twice which feels like an unnecessary double confirmation. Fortunately + it is easy to improve this! In my configuration I define the advice + `corfu-send-shell' which sends the candidate after insertion. + + ┌──── + │ (defun corfu-send-shell (&rest _) + │ "Send completion candidate when inside comint/eshell." + │ (cond + │ ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) + │ (eshell-send-input)) + │ ((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) + │ (comint-send-input)))) + │ + │ (advice-add #'corfu-insert :after #'corfu-send-shell) + └──── + + Shell completion uses the flexible Pcomplete mechanism internally, + which allows you to program the completions per shell command. If you + want to know more, look into this [blog post], which shows how to + configure Pcomplete for git commands. Since Emacs 29, Pcomplete + offers the `pcomplete-from-help' function which parses the `--help' + output of a command and produces completions for command line options. + + Pcomplete has a few bugs on Emacs 28 and older. We can work around the + issues with the [Cape] library (Completion at point extensions). Cape + provides wrappers which sanitize the Pcomplete function. If you use + Emacs 28 or older installing these advices is recommended such that + Pcomplete works properly. On Emacs 29 the advices should not be + necessary anymore, since most relevant bugs have been fixed. I + therefore recommend to avoid the advices on Emacs 29 and eventually + report any remaining Pcomplete issues upstream. + + ┌──── + │ ;; The advices are only needed on Emacs 28 and older. + │ (when (< emacs-major-version 29) + │ ;; Silence the pcomplete capf. Hide errors or messages. + │ (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent) + │ + │ ;; Ensure that pcomplete does not write to the buffer and behaves as a + │ ;; `completion-at-point-function' without side-effects. + │ (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)) + └──── + + +[blog post] +<https://www.masteringemacs.org/article/pcomplete-context-sensitive-completion-emacs> + +[Cape] <https://github.com/minad/cape> + + +4.4 Orderless completion +──────────────────────── + + [Orderless] is an advanced completion style that supports + multi-component search filters separated by a configurable character + (space, by default). Normally, entering characters like space which + lie outside the completion region boundaries (words, typically) causes + Corfu to quit. This behavior is helpful with auto-completion, which + may pop-up when not desired, e.g. on entering a new variable + name. Just keep typing and Corfu will get out of the way. + + But orderless search terms can contain arbitrary characters; they are + also interpreted as regular expressions. To use orderless, set + `corfu-separator' (a space, by default) to the primary character of + your orderless component separator. + + Then, when a new orderless component is desired, use `M-SPC' + (`corfu-insert-separator') to enter the first component separator in + the input, and arbitrary orderless search terms and new separators can + be entered thereafter. + + To treat the entire input as Orderless input, you can set the + customization option `corfu-quit-at-boundary' to nil. This disables + the predicate which checks if the current completion boundary has been + left. In contrast, if you always want to quit at the boundary, set + `corfu-quit-at-boundary' to t. By default `corfu-quit-at-boundary' is + set to `separator' which quits at completion boundaries as long as no + separator has been inserted with `corfu-insert-separator'. + + Finally, there exists the user option `corfu-quit-no-match' which is + set to `separator' by default. With this setting Corfu stays alive as + soon as you start advanced filtering with a `corfu-separator' even if + there are no matches, for example due to a typo. As long as no + separator character has been inserted with `corfu-insert-separator', + Corfu will still quit if there are no matches. This ensures that the + Corfu popup goes away quickly if completion is not possible. + + In the following we show two configurations, one which works best with + auto completion and one which may work better with manual completion + if you prefer to always use `SPC' to separate the Orderless + components. + + ┌──── + │ ;; Auto completion example + │ (use-package corfu + │ :custom + │ (corfu-auto t) ;; Enable auto completion + │ ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space + │ :bind + │ ;; Another key binding can be used, such as S-SPC. + │ ;; (:map corfu-map ("M-SPC" . corfu-insert-separator)) + │ :init + │ (global-corfu-mode)) + │ + │ ;; Manual completion example + │ (use-package corfu + │ :custom + │ ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space + │ :bind + │ ;; Configure SPC for separator insertion + │ (:map corfu-map ("SPC" . corfu-insert-separator)) + │ :init + │ (global-corfu-mode)) + └──── + + +[Orderless] <https://github.com/oantolin/orderless> + + +4.5 TAB-only completion +─────────────────────── + + By default, Corfu steals both the `RET' and `TAB' keys, when the Corfu + popup is open. This can feel intrusive, in particular in combination + with auto completion. `RET' may accidentally commit an automatically + selected candidate, while you actually wanted to start a new line. As + an alternative we can unbind the `RET' key completely from `corfu-map' + or reserve the `RET' key only in shell modes. + + ┌──── + │ ;; TAB-only configuration + │ (use-package corfu + │ :custom + │ (corfu-auto t) ;; Enable auto completion + │ (corfu-preselect 'directory) ;; Select the first candidate, except for directories + │ + │ ;; Free the RET key for less intrusive behavior. + │ :bind + │ (:map corfu-map + │ ;; Option 1: Unbind RET completely + │ ;;; ("RET" . nil) + │ ;; Option 2: Use RET only in shell modes + │ ("RET" . (menu-item "" nil :filter corfu-insert-shell-filter))) + │ + │ :init + │ (global-corfu-mode)) + │ + │ (defun corfu-insert-shell-filter (&optional _) + │ "Insert completion candidate and send when inside comint/eshell." + │ (when (or (derived-mode-p 'eshell-mode) (derived-mode-p 'comint-mode)) + │ (lambda () + │ (interactive) + │ (corfu-insert) + │ ;; `corfu-send-shell' was defined above + │ (corfu-send-shell)))) + └──── + + +4.6 TAB-and-Go completion +───────────────────────── + + You may be interested in configuring Corfu in TAB-and-Go + style. Pressing TAB moves to the next candidate and further input will + then commit the selection. Note that further input will not expand + snippets or templates, which may not be desired but which leads + overall to a more predictable behavior. In order to force snippet + expansion, confirm a candidate explicitly with `RET'. + + ┌──── + │ (use-package corfu + │ ;; TAB-and-Go customizations + │ :custom + │ (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' + │ (corfu-preselect 'prompt) ;; Always preselect the prompt + │ + │ ;; Use TAB for cycling, default is `corfu-complete'. + │ :bind + │ (:map corfu-map + │ ("TAB" . corfu-next) + │ ([tab] . corfu-next) + │ ("S-TAB" . corfu-previous) + │ ([backtab] . corfu-previous)) + │ + │ :init + │ (global-corfu-mode)) + └──── + + +4.7 Expanding to the common candidate prefix with TAB +───────────────────────────────────────────────────── + + If you leave the default configuration of the completion styles, such + that the `basic' completion style is still present, then pressing + `M-TAB' (`corfu-expand') will expand the current input to the common + prefix of all completion candidates. In contrast, `TAB' + (`corfu-complete') behaves differently and expands input to the + currently selected candidate. + + If you use the `orderless' completion style, then expansion works + differently by default. Orderless only expands to single matching + candidates, since due to its multi-component input, there does not + necessarily exist an expansion to a common candidate prefix. However + it is possible to define a separate `tab' completion style. The `tab' + completion style will only take over `TAB' completion (if prefix + expansion is possible), but besides that won't affect Orderless + candidate filtering. + + ┌──── + │ (add-to-list 'completion-styles-alist + │ '(tab completion-basic-try-completion ignore + │ "Completion style which provides TAB completion only.")) + │ (setq completion-styles '(tab orderless basic))) + └──── + + +4.8 Transfer completion to the minibuffer +───────────────────────────────────────── + + Sometimes it is useful to transfer the Corfu completion session to the + minibuffer, since the minibuffer offers richer interaction + features. In particular, [Embark] is available in the minibuffer, such + that you can act on the candidates or export/collect the candidates to + a separate buffer. We could add Corfu support to Embark in the future, + such that export or collect is possible directly from + Corfu. Nevertheless, the ability to transfer the Corfu completion to + the minibuffer is even more powerful, since further completion is + possible. + + The command `corfu-move-to-minibuffer' is defined here in terms of + `consult-completion-in-region', which uses the minibuffer completion + UI via `completing-read'. + + ┌──── + │ (defun corfu-move-to-minibuffer () + │ (interactive) + │ (pcase completion-in-region--data + │ (`(,beg ,end ,table ,pred ,extras) + │ (let ((completion-extra-properties extras) + │ completion-cycle-threshold completion-cycling) + │ (consult-completion-in-region beg end table pred))))) + │ (keymap-set corfu-map "M-m" #'corfu-move-to-minibuffer) + │ (add-to-list 'corfu-continue-commands #'corfu-move-to-minibuffer) + └──── + + +[Embark] <https://github.com/oantolin/embark> + + +5 Extensions +════════════ + + We maintain small extension packages to Corfu in this repository in + the subdirectory [extensions/]. The extensions are installed together + with Corfu if you pull the package from ELPA. The extensions are + inactive by default and can be enabled manually if + desired. Furthermore it is possible to install all of the files + separately, both `corfu.el' and the `corfu-*.el' extensions. Currently + the following extensions come with the Corfu ELPA package: + + • [corfu-echo]: `corfu-echo-mode' displays a brief candidate + documentation in the echo area. + • [corfu-history]: `corfu-history-mode' remembers selected candidates + and sorts the candidates by their history position. + • [corfu-indexed]: `corfu-indexed-mode' allows you to select indexed + candidates with prefix arguments. + • [corfu-info]: Actions to access the candidate location and + documentation. + • [corfu-popupinfo]: Display candidate documentation or source in a + popup next to the candidate menu. + • [corfu-quick]: Commands to select using Avy-style quick keys. + + See the Commentary of those files for configuration details. + + +[extensions/] <https://github.com/minad/corfu/tree/main/extensions> + +[corfu-echo] +<https://github.com/minad/corfu/blob/main/extensions/corfu-echo.el> + +[corfu-history] +<https://github.com/minad/corfu/blob/main/extensions/corfu-history.el> + +[corfu-indexed] +<https://github.com/minad/corfu/blob/main/extensions/corfu-indexed.el> + +[corfu-info] +<https://github.com/minad/corfu/blob/main/extensions/corfu-info.el> + +[corfu-popupinfo] +<https://github.com/minad/corfu/blob/main/extensions/corfu-popupinfo.el> + +[corfu-quick] +<https://github.com/minad/corfu/blob/main/extensions/corfu-quick.el> + + +6 Complementary packages +════════════════════════ + + Corfu works well together with all packages providing code completion + via the `completion-at-point-functions'. Many modes and packages + already provide a Capf out of the box. Nevertheless you may want to + look into complementary packages to enhance your setup. + + • [corfu-terminal]: The corfu-terminal package provides an + overlay-based display for Corfu, such that you can use Corfu in + terminal Emacs. + + • [corfu-candidate-overlay]: Shows as-you-type auto-suggestion + candidate overlay with a visual indication of whether there are many + or exactly one candidate available (works only with `corfu-auto' + disabled). + + • [Orderless]: Corfu supports completion styles, including the + advanced `orderless' completion style, where the filter expressions + are separated by spaces or another character (see + `corfu-separator'). + + • [Cape]: Provides additional Capf backends and `completion-in-region' + commands. Among others, the package supplies the file completion + backend `cape-file' and the Dabbrev backend `cape-dabbrev'. Cape + provides the `cape-company-to-capf' adapter to reuse Company + backends in Corfu. + + • [nerd-icons-corfu], [kind-icon]: Icons are supported by Corfu via + external packages. The nerd-icons-corfu package relies on the Nerd + icon font, which is even supported on terminal, while kind-icon uses + SVGs from monochromatic icon sets. + + • [Tempel]: Tiny template/snippet package with templates in Lisp + syntax, which can be used in conjunction with Corfu. + + • [Vertico]: You may also want to look into my Vertico + package. Vertico is the minibuffer completion counterpart of Corfu. + + +[corfu-terminal] <https://codeberg.org/akib/emacs-corfu-terminal> + +[corfu-candidate-overlay] +<https://code.bsdgeek.org/adam/corfu-candidate-overlay> + +[Orderless] <https://github.com/oantolin/orderless> + +[Cape] <https://github.com/minad/cape> + +[nerd-icons-corfu] <https://github.com/LuigiPiucco/nerd-icons-corfu> + +[kind-icon] <https://github.com/jdtsmith/kind-icon> + +[Tempel] <https://github.com/minad/tempel> + +[Vertico] <https://github.com/minad/vertico> + + +7 Alternatives +══════════════ + + • [Company]: Company is a widely used and mature completion package, + which implements a similar UI as Corfu. While Corfu relies + exclusively on the standard Emacs completion API (Capfs), Company + defines its own API for the backends. Company includes its own + completion backends, following its own API, which are incompatible + with the Emacs completion infrastructure. Company provides an + adapter `company-capf' to handle Capfs as a Company backend. As a + result of this design, Company is a more complex package than + Corfu. Company by default uses overlays for the popup in contrast to + the child frames used by Corfu. Overall both packages work well, but + Company integrates less tightly with Emacs. The `completion-styles' + support is more limited and the `completion-at-point' command and + the `completion-in-region' function do not invoke Company. + + • [consult-completion-in-region]: The Consult package provides the + function `consult-completion-in-region' which can be set as + `completion-in-region-function' such that it handles + `completion-at-point'. The function works by transferring the + in-buffer completion to the minibuffer. In the minibuffer, the + minibuffer completion UI, for example [Vertico] takes over. If you + prefer to perform all your completions in the minibuffer + `consult-completion-in-region' is your best option. + + +[Company] <https://github.com/company-mode/company-mode> + +[consult-completion-in-region] <https://github.com/minad/consult> + +[Vertico] <https://github.com/minad/vertico> + + +8 Debugging Corfu +═════════════════ + + When you observe an error in the `corfu--post-command' post command + hook, you should install an advice to enforce debugging. This allows + you to obtain a stack trace in order to narrow down the location of + the error. The reason is that post command hooks are automatically + disabled (and not debugged) by Emacs. Otherwise Emacs would become + unusable, given that the hooks are executed after every command. + + ┌──── + │ (setq debug-on-error t) + │ + │ (defun force-debug (func &rest args) + │ (condition-case e + │ (apply func args) + │ ((debug error) (signal (car e) (cdr e))))) + │ + │ (advice-add #'corfu--post-command :around #'force-debug) + └──── + + When Capfs do not yield the expected result you can use + `cape-capf-debug' to add debug messages to a Capf. The Capf will then + produce a completion log in the messages buffer. + + ┌──── + │ (setq completion-at-point-functions (list (cape-capf-debug #'cape-dict))) + └──── + + +9 Contributions +═══════════════ + + Since this package is part of [GNU ELPA] contributions require a + copyright assignment to the FSF. + + +[GNU ELPA] <https://elpa.gnu.org/packages/corfu.html> diff --git a/elpa/corfu-1.3/README.org b/elpa/corfu-1.3/README.org @@ -0,0 +1,644 @@ +#+title: corfu.el - COmpletion in Region FUnction +#+author: Daniel Mendler +#+language: en +#+export_file_name: corfu.texi +#+texinfo_dir_category: Emacs misc features +#+texinfo_dir_title: Corfu: (corfu). +#+texinfo_dir_desc: COmpletion in Region FUnction + +#+html: <a href="https://www.gnu.org/software/emacs/"><img alt="GNU Emacs" src="https://github.com/minad/corfu/blob/screenshots/emacs.svg?raw=true"/></a> +#+html: <a href="https://elpa.gnu.org/packages/corfu.html"><img alt="GNU ELPA" src="https://elpa.gnu.org/packages/corfu.svg"/></a> +#+html: <a href="https://elpa.gnu.org/devel/corfu.html"><img alt="GNU-devel ELPA" src="https://elpa.gnu.org/devel/corfu.svg"/></a> +#+html: <a href="https://melpa.org/#/corfu"><img alt="MELPA" src="https://melpa.org/packages/corfu-badge.svg"/></a> +#+html: <a href="https://stable.melpa.org/#/corfu"><img alt="MELPA Stable" src="https://stable.melpa.org/packages/corfu-badge.svg"/></a> + +Corfu enhances in-buffer completion with a small completion popup. The current +candidates are shown in a popup below or above the point. The candidates can be +selected by moving up and down. Corfu is the minimalistic in-buffer completion +counterpart of the [[https://github.com/minad/vertico][Vertico]] minibuffer UI. + +Corfu is a small package, which relies on the Emacs completion facilities and +concentrates on providing a polished completion UI. In-buffer completion UIs in +Emacs can hook into ~completion-in-region~, which implements the interaction with +the user. Completions at point are either provided by commands like +~dabbrev-completion~ or by pluggable backends (~completion-at-point-functions~, +Capfs) and are then passed to ~completion-in-region~. Many programming, text and +shell major modes implement a Capf. Corfu does not include its own completion +backends. The Emacs built-in Capfs and the Capfs provided by third-party +programming language packages are often sufficient. Additional Capfs and +completion utilities are provided by the [[https://github.com/minad/cape][Cape]] package. + +*NOTE*: Corfu uses child frames to show the popup and falls back to the default +setting of the ~completion-in-region-function~ on non-graphical displays. If you +want to use Corfu in the terminal, install the package [[https://codeberg.org/akib/emacs-corfu-terminal][corfu-terminal]], which +provides an alternative overlay-based display. + +#+html: <img src="https://github.com/minad/corfu/blob/screenshots/light.png?raw=true"> + +#+html: <img src="https://github.com/minad/corfu/blob/screenshots/dark.png?raw=true"> + +#+html: <img src="https://github.com/minad/corfu/blob/screenshots/popupinfo-light.png?raw=true"> + +#+html: <img src="https://github.com/minad/corfu/blob/screenshots/popupinfo-dark.png?raw=true"> + +#+toc: headlines 8 + +* Features + +- Timer-based auto-completions (/off/ by default, set ~corfu-auto~). +- Popup display with scrollbar indicator and arrow key navigation. +- The popup can be summoned explicitly by pressing =TAB= at any time. +- The current candidate is inserted with =TAB= and selected with =RET=. +- Candidate sorting by prefix, string length and alphabetically. +- The selected candidate is previewed (configurable via ~corfu-preview-current~). +- The selected candidate is automatically committed on further input by default. + (configurable via ~corfu-preview-current~). +- Supports the [[https://github.com/oantolin/orderless][Orderless]] completion style. The filter string can contain + arbitrary characters, after inserting a space via =M-SPC= (configurable via + ~corfu-quit-at-boundary~ and ~corfu-separator~). +- Lazy completion candidate highlighting for performance. +- Support for candidate annotations (=annotation-function=, =affixation-function=). +- Deprecated candidates are displayed as crossed out. +- Icons can be provided by an external package via margin formatter functions. +- Rich set of extensions: Quick keys, Index keys, Sorting by history, Candidate + documentation in echo area, popup or separate buffer. + +* Installation + +Corfu is available from [[https://elpa.gnu.org/packages/corfu.html][GNU ELPA]]. You can install it directly via =M-x package-install RET corfu RET=. +After installation, activate the global minor mode with =M-x global-corfu-mode RET=. +Set the variable ~corfu-auto~ to t in order to enable auto completion. For manual +completion press =M-TAB= (or =TAB=) within a buffer. + +* Key bindings + +Corfu uses a transient keymap ~corfu-map~ which is active while the popup is +shown. The keymap defines the following remappings of fundamental commands and +bindings: + +| Binding/Remapping | Corfu command | +|--------------------------+--------------------------| +| ~move-beginning-of-line~ | ~corfu-prompt-beginning~ | +| ~move-end-of-line~ | ~corfu-prompt-end~ | +| ~beginning-of-buffer~ | ~corfu-first~ | +| ~end-of-buffer~ | ~corfu-last~ | +| ~scroll-down-command~ | ~corfu-scroll-down~ | +| ~scroll-up-command~ | ~corfu-scroll-up~ | +| ~next-line~, =down=, =M-n= | ~corfu-next~ | +| ~previous-line~, =up=, =M-p= | ~corfu-previous~ | +| ~completion-at-point~, =TAB= | ~corfu-complete~ | +| =M-TAB= | ~corfu-expand~ | +| =RET= | ~corfu-insert~ | +| =M-g= | ~corfu-info-location~ | +| =M-h= | ~corfu-info-documentation~ | +| =M-SPC= | ~corfu-insert-separator~ | +| =C-g= | ~corfu-quit~ | +| ~keyboard-escape-quit~ | ~corfu-reset~ | + +* Configuration + +In order to configure Corfu and other packages in your init.el, you may want to +use ~use-package~. Corfu is flexibly customizable via ~corfu-*~ customization +variables, such that you can adapt it precisely to your requirements. However in +order to quickly try out the Corfu completion package, it should be sufficient +to activate ~global-corfu-mode~. You can experiment with manual completion for +example in an Elisp buffer or in an Eshell or Shell buffer. For auto completion, +set ~corfu-auto~ to t before turning on ~global-corfu-mode~. + +Here is an example configuration: + +#+begin_src emacs-lisp +(use-package corfu + ;; Optional customizations + ;; :custom + ;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' + ;; (corfu-auto t) ;; Enable auto completion + ;; (corfu-separator ?\s) ;; Orderless field separator + ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary + ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match + ;; (corfu-preview-current nil) ;; Disable current candidate preview + ;; (corfu-preselect 'prompt) ;; Preselect the prompt + ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches + ;; (corfu-scroll-margin 5) ;; Use scroll margin + + ;; Enable Corfu only for certain modes. + ;; :hook ((prog-mode . corfu-mode) + ;; (shell-mode . corfu-mode) + ;; (eshell-mode . corfu-mode)) + + ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can + ;; be used globally (M-/). See also the customization variable + ;; `global-corfu-modes' to exclude certain modes. + :init + (global-corfu-mode)) + +;; A few more useful configurations... +(use-package emacs + :init + ;; TAB cycle if there are only few candidates + ;; (setq completion-cycle-threshold 3) + + ;; Enable indentation+completion using the TAB key. + ;; `completion-at-point' is often bound to M-TAB. + (setq tab-always-indent 'complete) + + ;; Emacs 30 and newer: Disable Ispell completion function. As an alternative, + ;; try `cape-dict'. + (setq text-mode-ispell-word-completion nil) + + ;; Emacs 28 and newer: Hide commands in M-x which do not apply to the current + ;; mode. Corfu commands are hidden, since they are not used via M-x. This + ;; setting is useful beyond Corfu. + (setq read-extended-command-predicate #'command-completion-default-include-p)) +#+end_src + +Dabbrev completion is based on =completion-in-region= and can be used with Corfu. +You may want to swap the =dabbrev-completion= with the =dabbrev-expand= key for +easier access, if you prefer completion. Also take a look at the =cape-dabbrev= +completion at point function provided by my [[https://github.com/minad/cape][Cape]] package. + +#+begin_src emacs-lisp +;; Use Dabbrev with Corfu! +(use-package dabbrev + ;; Swap M-/ and C-M-/ + :bind (("M-/" . dabbrev-completion) + ("C-M-/" . dabbrev-expand)) + :config + (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ") + ;; Since 29.1, use `dabbrev-ignored-buffer-regexps' on older. + (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode) + (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode)) +#+end_src + +If you start to configure the package more deeply, I recommend to give the +Orderless completion style a try for filtering. Orderless completion is +different from the familiar prefix TAB completion. Corfu can be used with the +default completion styles. The use of Orderless is not a necessity. + +#+begin_src emacs-lisp +;; Optionally use the `orderless' completion style. +(use-package orderless + :init + ;; Configure a custom style dispatcher (see the Consult wiki) + ;; (setq orderless-style-dispatchers '(+orderless-dispatch) + ;; orderless-component-separator #'orderless-escapable-split-on-space) + (setq completion-styles '(orderless basic) + completion-category-defaults nil + completion-category-overrides '((file (styles partial-completion))))) +#+end_src + +The =basic= completion style is specified as fallback in addition to =orderless= in +order to ensure that completion commands which rely on dynamic completion +tables, e.g., ~completion-table-dynamic~ or ~completion-table-in-turn~, work +correctly. See =+orderless-dispatch= in the [[https://github.com/minad/consult/wiki][Consult wiki]] for an advanced Orderless +style dispatcher. Additionally enable =partial-completion= for file path +expansion. =partial-completion= is important for file wildcard support. Multiple +files can be opened at once with =find-file= if you enter a wildcard. You may also +give the =initials= completion style a try. + +See also the [[https://github.com/minad/corfu/wiki][Corfu Wiki]] and the [[https://github.com/minad/cape][Cape manual]] for additional Capf configuration +tips. For more general documentation read the chapter about completion in the +[[https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion.html][Emacs manual]]. If you want to create your own Capfs, you can find documentation +about completion in the [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion.html][Elisp manual]]. + +** Auto completion + +Auto completion is disabled by default, but can be enabled by setting ~corfu-auto~ +to t. Furthermore you may want to configure Corfu to quit completion eagerly, +such that the completion popup stays out of your way when it appeared +unexpectedly. + +#+begin_src emacs-lisp +;; Enable auto completion and configure quitting +(setq corfu-auto t + corfu-quit-no-match 'separator) ;; or t +#+end_src + +I suggest to experiment with the various settings and key bindings to find a +configuration which works for you. There is no one perfect configuration which +fits all. Some people like auto completion, some like manual completion, some +want to cycle with TAB and some with the arrow keys. + +In case you like auto completion settings, where the completion popup appears +immediately, better use a cheap completion style like =basic=, which performs +prefix filtering. In this case Corfu completion should still be fast in buffers +with efficient completion backends. You can try the following settings in an +Elisp buffer or the Emacs scratch buffer. Note that such settings can slow down +Emacs due to the high load on the Lisp runtime and garbage collector. + +#+begin_src emacs-lisp +(setq-local corfu-auto t + corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED + corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED + completion-styles '(basic)) +#+end_src + +If you want to combine fast prefix filtering and Orderless filtering you can +still do that by defining a custom Orderless completion style via +=orderless-define-completion-style=. We use a custom style dispatcher, which +enables efficient prefix filtering for input shorter than 4 characters. Note +that such a setup is advanced. Please refer to the Orderless documentation and +source code for further details. + +#+begin_src emacs-lisp +(defun orderless-fast-dispatch (word index total) + (and (= index 0) (= total 1) (length< word 4) + (cons 'orderless-literal-prefix word)))) + +(orderless-define-completion-style orderless-fast + (orderless-style-dispatchers '(orderless-fast-dispatch)) + (orderless-matching-styles '(orderless-literal orderless-regexp))) + +(setq-local corfu-auto t + corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED + corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED + completion-styles '(orderless-fast basic)) +#+end_src + +** Completing in the minibuffer + +Corfu can be used for completion in the minibuffer, since it relies on child +frames to display the candidates. The Corfu popup can be shown even if it +doesn't fully fit inside the minibuffer. + +By default, ~global-corfu-mode~ does not activate ~corfu-mode~ in the minibuffer, to +avoid interference with specialised minibuffer completion UIs like Vertico or +Mct. However you may still want to enable Corfu completion for commands like ~M-:~ +(~eval-expression~) or ~M-!~ (~shell-command~), which read from the minibuffer. In +order to detect minibuffers with completion we check if the variable +~completion-at-point-functions~ is set locally. + +#+begin_src emacs-lisp +(defun corfu-enable-in-minibuffer () + "Enable Corfu in the minibuffer." + (when (local-variable-p 'completion-at-point-functions) + ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion + (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) +#+end_src + +This is not recommended, but one can also enable Corfu more generally for every +minibuffer, as long as no completion UI is active. In the following example we +check for Mct and Vertico. Furthermore we ensure that Corfu is not enabled if a +password is read from the minibuffer. + +#+begin_src emacs-lisp +(defun corfu-enable-always-in-minibuffer () + "Enable Corfu in the minibuffer if Vertico/Mct are not active." + (unless (or (bound-and-true-p mct--active) + (bound-and-true-p vertico--input) + (eq (current-local-map) read-passwd-map)) + ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion + (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-always-in-minibuffer 1) +#+end_src + +** Completing in the Eshell or Shell + +When completing in the Eshell I recommend conservative local settings without +auto completion, such that the completion behavior is similar to widely used +shells like Bash, Zsh or Fish. + +#+begin_src emacs-lisp +(add-hook 'eshell-mode-hook + (lambda () + (setq-local corfu-auto nil) + (corfu-mode))) +#+end_src + +When pressing =RET= while the Corfu popup is visible, the ~corfu-insert~ command +will be invoked. This command does inserts the currently selected candidate, but +it does not send the prompt input to Eshell or the Comint process. Therefore you +often have to press =RET= twice which feels like an unnecessary double +confirmation. Fortunately it is easy to improve this! In my configuration I +define the advice ~corfu-send-shell~ which sends the candidate after insertion. + +#+begin_src emacs-lisp +(defun corfu-send-shell (&rest _) + "Send completion candidate when inside comint/eshell." + (cond + ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) + (eshell-send-input)) + ((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) + (comint-send-input)))) + +(advice-add #'corfu-insert :after #'corfu-send-shell) +#+end_src + +Shell completion uses the flexible Pcomplete mechanism internally, which allows +you to program the completions per shell command. If you want to know more, look +into this [[https://www.masteringemacs.org/article/pcomplete-context-sensitive-completion-emacs][blog post]], which shows how to configure Pcomplete for git commands. +Since Emacs 29, Pcomplete offers the =pcomplete-from-help= function which parses +the ~--help~ output of a command and produces completions for command line +options. + +Pcomplete has a few bugs on Emacs 28 and older. We can work around the issues +with the [[https://github.com/minad/cape][Cape]] library (Completion at point extensions). Cape provides wrappers +which sanitize the Pcomplete function. If you use Emacs 28 or older installing +these advices is recommended such that Pcomplete works properly. On Emacs 29 the +advices should not be necessary anymore, since most relevant bugs have been +fixed. I therefore recommend to avoid the advices on Emacs 29 and eventually +report any remaining Pcomplete issues upstream. + +#+begin_src emacs-lisp +;; The advices are only needed on Emacs 28 and older. +(when (< emacs-major-version 29) + ;; Silence the pcomplete capf. Hide errors or messages. + (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent) + + ;; Ensure that pcomplete does not write to the buffer and behaves as a + ;; `completion-at-point-function' without side-effects. + (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)) +#+end_src + +** Orderless completion + +[[https://github.com/oantolin/orderless][Orderless]] is an advanced completion style that supports multi-component search +filters separated by a configurable character (space, by default). Normally, +entering characters like space which lie outside the completion region +boundaries (words, typically) causes Corfu to quit. This behavior is helpful +with auto-completion, which may pop-up when not desired, e.g. on entering a new +variable name. Just keep typing and Corfu will get out of the way. + +But orderless search terms can contain arbitrary characters; they are also +interpreted as regular expressions. To use orderless, set ~corfu-separator~ (a +space, by default) to the primary character of your orderless component +separator. + +Then, when a new orderless component is desired, use =M-SPC= +(~corfu-insert-separator~) to enter the first component separator in the input, +and arbitrary orderless search terms and new separators can be entered +thereafter. + +To treat the entire input as Orderless input, you can set the customization +option ~corfu-quit-at-boundary~ to nil. This disables the predicate which checks +if the current completion boundary has been left. In contrast, if you always +want to quit at the boundary, set ~corfu-quit-at-boundary~ to t. By default +~corfu-quit-at-boundary~ is set to ~separator~ which quits at completion boundaries +as long as no separator has been inserted with ~corfu-insert-separator~. + +Finally, there exists the user option ~corfu-quit-no-match~ which is set to +=separator= by default. With this setting Corfu stays alive as soon as you start +advanced filtering with a ~corfu-separator~ even if there are no matches, for +example due to a typo. As long as no separator character has been inserted with +~corfu-insert-separator~, Corfu will still quit if there are no matches. This +ensures that the Corfu popup goes away quickly if completion is not possible. + +In the following we show two configurations, one which works best with auto +completion and one which may work better with manual completion if you prefer to +always use =SPC= to separate the Orderless components. + + #+begin_src emacs-lisp +;; Auto completion example +(use-package corfu + :custom + (corfu-auto t) ;; Enable auto completion + ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space + :bind + ;; Another key binding can be used, such as S-SPC. + ;; (:map corfu-map ("M-SPC" . corfu-insert-separator)) + :init + (global-corfu-mode)) + +;; Manual completion example +(use-package corfu + :custom + ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space + :bind + ;; Configure SPC for separator insertion + (:map corfu-map ("SPC" . corfu-insert-separator)) + :init + (global-corfu-mode)) +#+end_src + +** TAB-only completion + +By default, Corfu steals both the ~RET~ and ~TAB~ keys, when the Corfu popup is +open. This can feel intrusive, in particular in combination with auto +completion. ~RET~ may accidentally commit an automatically selected candidate, +while you actually wanted to start a new line. As an alternative we can unbind +the ~RET~ key completely from ~corfu-map~ or reserve the ~RET~ key only in shell +modes. + +#+begin_src emacs-lisp +;; TAB-only configuration +(use-package corfu + :custom + (corfu-auto t) ;; Enable auto completion + (corfu-preselect 'directory) ;; Select the first candidate, except for directories + + ;; Free the RET key for less intrusive behavior. + :bind + (:map corfu-map + ;; Option 1: Unbind RET completely + ;;; ("RET" . nil) + ;; Option 2: Use RET only in shell modes + ("RET" . (menu-item "" nil :filter corfu-insert-shell-filter))) + + :init + (global-corfu-mode)) + +(defun corfu-insert-shell-filter (&optional _) + "Insert completion candidate and send when inside comint/eshell." + (when (or (derived-mode-p 'eshell-mode) (derived-mode-p 'comint-mode)) + (lambda () + (interactive) + (corfu-insert) + ;; `corfu-send-shell' was defined above + (corfu-send-shell)))) +#+end_src + +** TAB-and-Go completion + +You may be interested in configuring Corfu in TAB-and-Go style. Pressing TAB +moves to the next candidate and further input will then commit the selection. +Note that further input will not expand snippets or templates, which may not be +desired but which leads overall to a more predictable behavior. In order to +force snippet expansion, confirm a candidate explicitly with ~RET~. + +#+begin_src emacs-lisp +(use-package corfu + ;; TAB-and-Go customizations + :custom + (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' + (corfu-preselect 'prompt) ;; Always preselect the prompt + + ;; Use TAB for cycling, default is `corfu-complete'. + :bind + (:map corfu-map + ("TAB" . corfu-next) + ([tab] . corfu-next) + ("S-TAB" . corfu-previous) + ([backtab] . corfu-previous)) + + :init + (global-corfu-mode)) +#+end_src + +** Expanding to the common candidate prefix with TAB + +If you leave the default configuration of the completion styles, such that the +~basic~ completion style is still present, then pressing ~M-TAB~ (~corfu-expand~) will +expand the current input to the common prefix of all completion candidates. In +contrast, ~TAB~ (~corfu-complete~) behaves differently and expands input to the +currently selected candidate. + +If you use the ~orderless~ completion style, then expansion works differently by +default. Orderless only expands to single matching candidates, since due to its +multi-component input, there does not necessarily exist an expansion to a common +candidate prefix. However it is possible to define a separate ~tab~ completion +style. The ~tab~ completion style will only take over ~TAB~ completion (if prefix +expansion is possible), but besides that won't affect Orderless candidate +filtering. + +#+begin_src emacs-lisp +(add-to-list 'completion-styles-alist + '(tab completion-basic-try-completion ignore + "Completion style which provides TAB completion only.")) +(setq completion-styles '(tab orderless basic))) +#+end_src + +** Transfer completion to the minibuffer + +Sometimes it is useful to transfer the Corfu completion session to the +minibuffer, since the minibuffer offers richer interaction features. In +particular, [[https://github.com/oantolin/embark][Embark]] is available in the minibuffer, such that you can act on the +candidates or export/collect the candidates to a separate buffer. We could add +Corfu support to Embark in the future, such that export or collect is possible +directly from Corfu. Nevertheless, the ability to transfer the Corfu completion +to the minibuffer is even more powerful, since further completion is possible. + +The command ~corfu-move-to-minibuffer~ is defined here in terms of +~consult-completion-in-region~, which uses the minibuffer completion UI via +~completing-read~. + +#+begin_src emacs-lisp +(defun corfu-move-to-minibuffer () + (interactive) + (pcase completion-in-region--data + (`(,beg ,end ,table ,pred ,extras) + (let ((completion-extra-properties extras) + completion-cycle-threshold completion-cycling) + (consult-completion-in-region beg end table pred))))) +(keymap-set corfu-map "M-m" #'corfu-move-to-minibuffer) +(add-to-list 'corfu-continue-commands #'corfu-move-to-minibuffer) +#+end_src + +* Extensions +:properties: +:custom_id: extensions +:end: + +We maintain small extension packages to Corfu in this repository in the +subdirectory [[https://github.com/minad/corfu/tree/main/extensions][extensions/]]. The extensions are installed together with Corfu if +you pull the package from ELPA. The extensions are inactive by default and can +be enabled manually if desired. Furthermore it is possible to install all of the +files separately, both ~corfu.el~ and the ~corfu-*.el~ extensions. Currently the +following extensions come with the Corfu ELPA package: + +- [[https://github.com/minad/corfu/blob/main/extensions/corfu-echo.el][corfu-echo]]: =corfu-echo-mode= displays a brief candidate documentation in the + echo area. +- [[https://github.com/minad/corfu/blob/main/extensions/corfu-history.el][corfu-history]]: =corfu-history-mode= remembers selected candidates and sorts the + candidates by their history position. +- [[https://github.com/minad/corfu/blob/main/extensions/corfu-indexed.el][corfu-indexed]]: =corfu-indexed-mode= allows you to select indexed candidates with + prefix arguments. +- [[https://github.com/minad/corfu/blob/main/extensions/corfu-info.el][corfu-info]]: Actions to access the candidate location and documentation. +- [[https://github.com/minad/corfu/blob/main/extensions/corfu-popupinfo.el][corfu-popupinfo]]: Display candidate documentation or source in a popup next to + the candidate menu. +- [[https://github.com/minad/corfu/blob/main/extensions/corfu-quick.el][corfu-quick]]: Commands to select using Avy-style quick keys. + +See the Commentary of those files for configuration details. + +* Complementary packages + +Corfu works well together with all packages providing code completion via the +~completion-at-point-functions~. Many modes and packages already provide a Capf +out of the box. Nevertheless you may want to look into complementary packages to +enhance your setup. + +- [[https://codeberg.org/akib/emacs-corfu-terminal][corfu-terminal]]: The corfu-terminal package provides an overlay-based display + for Corfu, such that you can use Corfu in terminal Emacs. + +- [[https://code.bsdgeek.org/adam/corfu-candidate-overlay][corfu-candidate-overlay]]: Shows as-you-type auto-suggestion candidate overlay + with a visual indication of whether there are many or exactly one candidate + available (works only with =corfu-auto= disabled). + +- [[https://github.com/oantolin/orderless][Orderless]]: Corfu supports completion styles, including the advanced =orderless= + completion style, where the filter expressions are separated by spaces or + another character (see ~corfu-separator~). + +- [[https://github.com/minad/cape][Cape]]: Provides additional Capf backends and =completion-in-region= commands. + Among others, the package supplies the file completion backend =cape-file= and + the Dabbrev backend =cape-dabbrev=. Cape provides the ~cape-company-to-capf~ + adapter to reuse Company backends in Corfu. + +- [[https://github.com/LuigiPiucco/nerd-icons-corfu][nerd-icons-corfu]], [[https://github.com/jdtsmith/kind-icon][kind-icon]]: Icons are supported by Corfu via external + packages. The nerd-icons-corfu package relies on the Nerd icon font, which is + even supported on terminal, while kind-icon uses SVGs from monochromatic icon + sets. + +- [[https://github.com/minad/tempel][Tempel]]: Tiny template/snippet package with templates in Lisp syntax, which + can be used in conjunction with Corfu. + +- [[https://github.com/minad/vertico][Vertico]]: You may also want to look into my Vertico package. Vertico is the + minibuffer completion counterpart of Corfu. + +* Alternatives + +- [[https://github.com/company-mode/company-mode][Company]]: Company is a widely used and mature completion package, which + implements a similar UI as Corfu. While Corfu relies exclusively on the + standard Emacs completion API (Capfs), Company defines its own API for the + backends. Company includes its own completion backends, following its own API, + which are incompatible with the Emacs completion infrastructure. Company + provides an adapter ~company-capf~ to handle Capfs as a Company backend. As a + result of this design, Company is a more complex package than Corfu. Company + by default uses overlays for the popup in contrast to the child frames used by + Corfu. Overall both packages work well, but Company integrates less tightly + with Emacs. The ~completion-styles~ support is more limited and the + ~completion-at-point~ command and the ~completion-in-region~ function do not + invoke Company. + +- [[https://github.com/minad/consult][consult-completion-in-region]]: The Consult package provides the function + ~consult-completion-in-region~ which can be set as ~completion-in-region-function~ + such that it handles ~completion-at-point~. The function works by transferring + the in-buffer completion to the minibuffer. In the minibuffer, the minibuffer + completion UI, for example [[https://github.com/minad/vertico][Vertico]] takes over. If you prefer to perform all + your completions in the minibuffer ~consult-completion-in-region~ is your best + option. + +* Debugging Corfu + +When you observe an error in the =corfu--post-command= post command hook, you +should install an advice to enforce debugging. This allows you to obtain a stack +trace in order to narrow down the location of the error. The reason is that post +command hooks are automatically disabled (and not debugged) by Emacs. Otherwise +Emacs would become unusable, given that the hooks are executed after every +command. + +#+begin_src emacs-lisp +(setq debug-on-error t) + +(defun force-debug (func &rest args) + (condition-case e + (apply func args) + ((debug error) (signal (car e) (cdr e))))) + +(advice-add #'corfu--post-command :around #'force-debug) +#+end_src + +When Capfs do not yield the expected result you can use ~cape-capf-debug~ to add +debug messages to a Capf. The Capf will then produce a completion log in the +messages buffer. + +#+begin_src emacs-lisp +(setq completion-at-point-functions (list (cape-capf-debug #'cape-dict))) +#+end_src + +* Contributions + +Since this package is part of [[https://elpa.gnu.org/packages/corfu.html][GNU ELPA]] contributions require a copyright +assignment to the FSF. diff --git a/elpa/corfu-1.0/corfu-autoloads.el b/elpa/corfu-1.3/corfu-autoloads.el diff --git a/elpa/corfu-1.3/corfu-echo.el b/elpa/corfu-1.3/corfu-echo.el @@ -0,0 +1,109 @@ +;;; corfu-echo.el --- Show candidate documentation in echo area -*- lexical-binding: t -*- + +;; Copyright (C) 2021-2024 Free Software Foundation, Inc. + +;; Author: Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2022 +;; Version: 1.3 +;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.3")) +;; Homepage: https://github.com/minad/corfu + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Show candidate documentation in echo area. Enable `corfu-echo-mode'. + +;;; Code: + +(require 'corfu) +(eval-when-compile + (require 'subr-x)) + +(defface corfu-echo + '((t :inherit completions-annotations)) + "Face used for echo area messages." + :group 'corfu-faces) + +(defcustom corfu-echo-delay '(2.0 . 1.0) + "Show documentation string in the echo area after that number of seconds. +The value can be a pair of two floats to specify initial and +subsequent delay." + :type '(choice (const :tag "Never" nil) + (number :tag "Delay in seconds") + (cons :tag "Two Delays" + (choice :tag "Initial " number) + (choice :tag "Subsequent" number))) + :group 'corfu) + +(defvar corfu-echo--timer nil + "Echo area message timer.") + +(defvar corfu-echo--message nil + "Last echo message.") + +(defun corfu-echo--cancel (&optional msg) + "Cancel echo timer and refresh MSG." + (when corfu-echo--timer + (cancel-timer corfu-echo--timer) + (setq corfu-echo--timer nil)) + (corfu-echo--show msg) + (unless corfu-echo--message + (setq corfu-echo--timer nil + corfu-echo--message nil))) + +(defun corfu-echo--show (msg) + "Show MSG in echo area." + (when (or msg corfu-echo--message) + (setq msg (or msg "") + corfu-echo--message msg) + (corfu--message "%s" (if (text-property-not-all 0 (length msg) 'face nil msg) + msg + (propertize msg 'face 'corfu-echo))))) + +;;;###autoload +(define-minor-mode corfu-echo-mode + "Show candidate documentation in echo area." + :global t :group 'corfu) + +(cl-defmethod corfu--exhibit :after (&context (corfu-echo-mode (eql t)) &optional _auto) + (if-let ((delay (if (consp corfu-echo-delay) + (funcall (if corfu-echo--message #'cdr #'car) + corfu-echo-delay) + corfu-echo-delay)) + (extra (nth 4 completion-in-region--data)) + (fun (plist-get extra :company-docsig)) + (cand (and (>= corfu--index 0) + (nth corfu--index corfu--candidates)))) + (if (<= delay 0) + (corfu-echo--show (funcall fun cand)) + (corfu-echo--cancel) + (setq corfu-echo--timer + (run-at-time delay nil + (lambda () + (corfu-echo--show (funcall fun cand)))))) + (corfu-echo--cancel))) + +(cl-defmethod corfu--teardown :before (_buf &context (corfu-echo-mode (eql t))) + (corfu-echo--cancel)) + +(cl-defmethod corfu--prepare :before (&context (corfu-echo-mode (eql t))) + ;; The refreshing is needed to prevent flicker if corfu-echo-delay=t. + (corfu-echo--cancel corfu-echo--message)) + +(provide 'corfu-echo) +;;; corfu-echo.el ends here diff --git a/elpa/corfu-1.3/corfu-history.el b/elpa/corfu-1.3/corfu-history.el @@ -0,0 +1,92 @@ +;;; corfu-history.el --- Sorting by history for Corfu -*- lexical-binding: t -*- + +;; Copyright (C) 2022-2024 Free Software Foundation, Inc. + +;; Author: Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2022 +;; Version: 1.3 +;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.3")) +;; Homepage: https://github.com/minad/corfu + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Enable `corfu-history-mode' to sort candidates by their history +;; position. Maintain a list of recently selected candidates. In order +;; to save the history across Emacs sessions, enable `savehist-mode' and +;; add `corfu-history' to `savehist-additional-variables'. +;; +;; (corfu-history-mode 1) +;; (savehist-mode 1) +;; (add-to-list 'savehist-additional-variables 'corfu-history) + +;;; Code: + +(require 'corfu) +(eval-when-compile + (require 'cl-lib)) + +(defvar corfu-history nil + "History of Corfu candidates. +The maximum length is determined by the variable `history-length' +or the property `history-length' of `corfu-history'.") + +(defvar corfu-history--hash nil + "Hash table of Corfu candidates.") + +(defun corfu-history--sort-predicate (x y) + "Sorting predicate which compares X and Y." + (or (< (cdr x) (cdr y)) + (and (= (cdr x) (cdr y)) + (corfu--length-string< (car x) (car y))))) + +(defun corfu-history--sort (cands) + "Sort CANDS by history." + (unless corfu-history--hash + (setq corfu-history--hash (make-hash-table :test #'equal :size (length corfu-history))) + (cl-loop for elem in corfu-history for index from 0 do + (unless (gethash elem corfu-history--hash) + (puthash elem index corfu-history--hash)))) + ;; Decorate each candidate with (index<<13) + length. This way we sort first by index and then by + ;; length. We assume that the candidates are shorter than 2**13 characters and that the history is + ;; shorter than 2**16 entries. + (cl-loop for cand on cands do + (setcar cand (cons (car cand) + (+ (ash (gethash (car cand) corfu-history--hash #xFFFF) 13) + (length (car cand)))))) + (setq cands (sort cands #'corfu-history--sort-predicate)) + (cl-loop for cand on cands do (setcar cand (caar cand))) + cands) + +;;;###autoload +(define-minor-mode corfu-history-mode + "Update Corfu history and sort completions by history." + :global t :group 'corfu + (if corfu-history-mode + (add-function :override corfu-sort-function #'corfu-history--sort) + (remove-function corfu-sort-function #'corfu-history--sort))) + +(cl-defmethod corfu--insert :before (_status &context (corfu-history-mode (eql t))) + (when (>= corfu--index 0) + (add-to-history 'corfu-history + (substring-no-properties + (nth corfu--index corfu--candidates))) + (setq corfu-history--hash nil))) + +(provide 'corfu-history) +;;; corfu-history.el ends here diff --git a/elpa/corfu-1.3/corfu-indexed.el b/elpa/corfu-1.3/corfu-indexed.el @@ -0,0 +1,97 @@ +;;; corfu-indexed.el --- Select indexed candidates -*- lexical-binding: t -*- + +;; Copyright (C) 2022-2024 Free Software Foundation, Inc. + +;; Author: Luis Henriquez-Perez <luis@luishp.xyz>, Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2022 +;; Version: 1.3 +;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.3")) +;; Homepage: https://github.com/minad/corfu + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This package is a Corfu extension, which prefixes candidates with indices if +;; enabled via `corfu-indexed-mode'. It allows you to select candidates with +;; prefix arguments. This is designed to be a faster alternative to selecting a +;; candidate with `corfu-next' and `corfu-previous'. + +;;; Code: + +(require 'corfu) +(eval-when-compile + (require 'cl-lib)) + +(defface corfu-indexed + '((default :height 0.75) + (((class color) (min-colors 88) (background dark)) + :foreground "#f4f4f4" :background "#323232") + (((class color) (min-colors 88) (background light)) + :foreground "#404148" :background "#d7d7d7") + (t :background "black")) + "Face used for the candidate index prefix." + :group 'corfu-faces) + +(defcustom corfu-indexed-start 0 + "Start of the indexing." + :group 'corfu + :type 'natnum) + +(defvar corfu-indexed--commands + '(corfu-insert corfu-complete) + "Commands that should be indexed.") + +;;;###autoload +(define-minor-mode corfu-indexed-mode + "Prefix candidates with indices." + :global t :group 'corfu) + +(cl-defmethod corfu--prepare :before (&context (corfu-indexed-mode (eql t))) + (when (and prefix-arg (memq this-command corfu-indexed--commands)) + (let ((index (+ corfu--scroll + (- (prefix-numeric-value prefix-arg) + corfu-indexed-start)))) + (if (and (>= index 0) + (< index corfu--total) + (< index (+ corfu--scroll corfu-count))) + (setq corfu--index index) + (message "Out of range") + (setq this-command #'ignore))))) + +(cl-defmethod corfu--affixate :around (cands &context (corfu-indexed-mode (eql t))) + (setq cands (cdr (cl-call-next-method cands))) + (let* ((space #(" " 0 1 (face (:height 0.5 :inherit corfu-indexed)))) + (width (if (length> cands (- 10 corfu-indexed-start)) 2 1)) + (fmt (concat space + (propertize (format "%%%ds" width) + 'face 'corfu-indexed) + space)) + (align + (propertize (make-string width ?\s) + 'display + `(space :align-to (+ left ,(1+ width)))))) + (cl-loop for cand in cands for index from corfu-indexed-start do + (setf (cadr cand) + (concat + (propertize " " 'display (format fmt index)) + align + (cadr cand)))) + (cons t cands))) + +(provide 'corfu-indexed) +;;; corfu-indexed.el ends here diff --git a/elpa/corfu-1.3/corfu-info.el b/elpa/corfu-1.3/corfu-info.el @@ -0,0 +1,118 @@ +;;; corfu-info.el --- Show candidate information in separate buffer -*- lexical-binding: t -*- + +;; Copyright (C) 2022-2024 Free Software Foundation, Inc. + +;; Author: Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2022 +;; Version: 1.3 +;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.3")) +;; Homepage: https://github.com/minad/corfu + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This Corfu extension provides commands to show additional information to the +;; candidates in a separate buffer. The commands `corfu-info-location' and +;; `corfu-info-documentation' are bound by default in the `corfu-map' to M-g and +;; M-h respectively. + +;;; Code: + +(require 'corfu) +(eval-when-compile + (require 'subr-x)) + +(defun corfu-info--restore-on-next-command () + "Restore window configuration before next command." + (let ((config (current-window-configuration)) + (other other-window-scroll-buffer) + (restore (make-symbol "corfu--restore"))) + (fset restore + (lambda () + (setq other-window-scroll-buffer other) + (unless (memq this-command '(scroll-other-window scroll-other-window-down)) + (when (memq this-command '(corfu-quit corfu-reset)) + (setq this-command #'ignore)) + (remove-hook 'pre-command-hook restore) + (set-window-configuration config)))) + (add-hook 'pre-command-hook restore))) + +(defun corfu-info--display-buffer (buffer name) + "Display BUFFER and return window displaying the buffer. +Make the buffer persistent with NAME if non-nil." + (if name + (unless (buffer-local-value 'buffer-file-name buffer) + (if-let ((old (get-buffer name))) + (setq buffer (prog1 old (kill-buffer buffer))) + (with-current-buffer buffer + (rename-buffer name)))) + (corfu-info--restore-on-next-command)) + (setq other-window-scroll-buffer buffer) + (display-buffer buffer t)) + +;;;###autoload +(defun corfu-info-documentation (&optional arg) + "Show documentation of current candidate. +If called with a prefix ARG, the buffer is persistent." + (interactive "P") + ;; Company support, taken from `company.el', see `company-show-doc-buffer'. + (when (< corfu--index 0) + (user-error "No candidate selected")) + (let ((cand (nth corfu--index corfu--candidates))) + (if-let ((extra (nth 4 completion-in-region--data)) + (fun (plist-get extra :company-doc-buffer)) + (res (funcall fun cand))) + (set-window-start (corfu-info--display-buffer + (get-buffer (or (car-safe res) res)) + (and arg (format "*corfu doc: %s*" cand))) + (or (cdr-safe res) (point-min))) + (user-error "No documentation available for `%s'" cand)))) + +;;;###autoload +(defun corfu-info-location (&optional arg) + "Show location of current candidate. +If called with a prefix ARG, the buffer is persistent." + (interactive "P") + ;; Company support, taken from `company.el', see `company-show-location'. + (when (< corfu--index 0) + (user-error "No candidate selected")) + (let ((cand (nth corfu--index corfu--candidates))) + (if-let ((extra (nth 4 completion-in-region--data)) + (fun (plist-get extra :company-location)) + ;; BUG: company-location may throw errors if location is not found + (loc (ignore-errors (funcall fun cand)))) + (with-selected-window + (corfu-info--display-buffer + (or (and (bufferp (car loc)) (car loc)) + (find-file-noselect (car loc) t)) + (and arg (format "*corfu loc: %s*" cand))) + (without-restriction + (goto-char (point-min)) + (when-let ((pos (cdr loc))) + (if (bufferp (car loc)) + (goto-char pos) + (forward-line (1- pos)))) + (set-window-start nil (point)))) + (user-error "No location available for `%s'" cand)))) + +;; Emacs 28: Do not show Corfu commands with M-X +(put #'corfu-info-location 'completion-predicate #'ignore) +(put #'corfu-info-documentation 'completion-predicate #'ignore) + +(provide 'corfu-info) +;;; corfu-info.el ends here diff --git a/elpa/corfu-1.3/corfu-pkg.el b/elpa/corfu-1.3/corfu-pkg.el @@ -0,0 +1,2 @@ +;; Generated package description from corfu.el -*- no-byte-compile: t -*- +(define-package "corfu" "1.3" "COmpletion in Region FUnction" '((emacs "27.1") (compat "29.1.4.4")) :commit "6088f0550dc8f10f5bcf6f24d35ce24159b01b43" :authors '(("Daniel Mendler" . "mail@daniel-mendler.de")) :maintainer '("Daniel Mendler" . "mail@daniel-mendler.de") :keywords '("abbrev" "convenience" "matching" "completion" "text") :url "https://github.com/minad/corfu") diff --git a/elpa/corfu-1.3/corfu-popupinfo.el b/elpa/corfu-1.3/corfu-popupinfo.el @@ -0,0 +1,523 @@ +;;; corfu-popupinfo.el --- Candidate information popup for Corfu -*- lexical-binding: t -*- + +;; Copyright (C) 2021-2024 Free Software Foundation, Inc. + +;; Author: Yuwei Tian <fishtai0@gmail.com>, Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2022 +;; Version: 1.3 +;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.3")) +;; Homepage: https://github.com/minad/corfu + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Display an information popup for completion candidate when using +;; Corfu. The popup displays either the candidate documentation or the +;; candidate location. The `corfu-popupinfo-mode' must be enabled +;; globally. Set `corfu-popupinfo-delay' to nil if the info popup should +;; not update automatically. If the popup should not appear initially, +;; but update automatically afterwards, use `(setq corfu-popupinfo-delay +;; (cons nil 1.0))'. + +;; For manual toggling the commands `corfu-popupinfo-toggle', +;; `corfu-popupinfo-location' and `corfu-popupinfo-documentation' are +;; bound in the `corfu-popupinfo-map'. + +;;; Code: + +(require 'corfu) +(eval-when-compile + (require 'cl-lib) + (require 'subr-x)) + +(defface corfu-popupinfo + '((t :inherit corfu-default)) + "Face used for the info popup." + :group 'corfu-faces) + +(defcustom corfu-popupinfo-delay '(2.0 . 1.0) + "Automatically update info popup after that number of seconds. + +The value can be a pair of two floats to specify initial and +subsequent delay. If the value is non-nil or the car of the pair +is non-nil, the popup will automatically appear for the +preselected candidate. Otherwise the popup can be requested +manually via `corfu-popupinfo-toggle', +`corfu-popupinfo-documentation' and `corfu-popupinfo-location'. + +It is *not recommended* to use a short delay or even 0, since +this will create high load for Emacs. Retrieving the +documentation from the backend is usually expensive." + :type '(choice (const :tag "Never" nil) + (number :tag "Delay in seconds") + (cons :tag "Two Delays" + (choice :tag "Initial " + (choice (const nil) number)) + (choice :tag "Subsequent" + (choice (const nil) number)))) + :group 'corfu) + +(defcustom corfu-popupinfo-hide t + "Hide the popup during the transition between candidates." + :type 'boolean + :group 'corfu) + +(defcustom corfu-popupinfo-max-width 80 + "The maximum width of the info popup in characters." + :type 'natnum + :group 'corfu) + +(defcustom corfu-popupinfo-min-width 30 + "The minimum width of the info popup in characters." + :type 'natnum + :group 'corfu) + +(defcustom corfu-popupinfo-max-height 10 + "The maximum height of the info popup in characters." + :type 'natnum + :group 'corfu) + +(defcustom corfu-popupinfo-min-height 1 + "The minimum height of the info popup in characters." + :type 'natnum + :group 'corfu) + +(defcustom corfu-popupinfo-resize t + "Resize the info popup automatically if non-nil." + :type 'boolean + :group 'corfu) + +(defcustom corfu-popupinfo-direction '(right left vertical) + "Preferred directions for the popup in order." + :type '(repeat + (choice + (const left) + (const right) + (const vertical) + (const force-left) + (const force-right) + (const force-vertical))) + :group 'corfu) + +(defvar-keymap corfu-popupinfo-map + :doc "Additional keymap activated in popupinfo mode." + "M-t" #'corfu-popupinfo-toggle + "<remap> <corfu-info-documentation>" #'corfu-popupinfo-documentation + "<remap> <corfu-info-location>" #'corfu-popupinfo-location + "<remap> <scroll-other-window>" #'corfu-popupinfo-scroll-up + "<remap> <scroll-other-window-down>" #'corfu-popupinfo-scroll-down + "<remap> <end-of-buffer-other-window>" #'corfu-popupinfo-end + "<remap> <beginning-of-buffer-other-window>" #'corfu-popupinfo-beginning) + +(defvar corfu-popupinfo--buffer-parameters + '((truncate-partial-width-windows . nil) + (truncate-lines . nil) + (left-margin-width . 1) + (right-margin-width . 1) + (word-wrap . t) + (fringe-indicator-alist (continuation))) + "Buffer parameters.") + +(defvar corfu-popupinfo--frame nil + "Info popup child frame.") + +(defvar corfu-popupinfo--timer nil + "Corfu info popup auto display timer.") + +(defvar corfu-popupinfo--toggle 'init + "Toggle state.") + +(defvar corfu-popupinfo--function + #'corfu-popupinfo--get-documentation + "Function called to obtain documentation string.") + +(defvar corfu-popupinfo--candidate nil + "Completion candidate for the info popup.") + +(defvar corfu-popupinfo--coordinates nil + "Coordinates of the candidate popup. +The coordinates list has the form (LEFT TOP RIGHT BOTTOM) where +all values are in pixels relative to the origin. See +`frame-edges' for details.") + +(defvar corfu-popupinfo--lock-dir nil + "Locked position direction of the info popup.") + +(defconst corfu-popupinfo--initial-state + (mapcar + (lambda (k) (cons k (symbol-value k))) + '(corfu-popupinfo--candidate + corfu-popupinfo--coordinates + corfu-popupinfo--lock-dir + corfu-popupinfo--toggle + corfu-popupinfo--function)) + "Initial state of `corfu-popupinfo-mode'.") + +(defun corfu-popupinfo--visible-p (&optional frame) + "Return non-nil if FRAME is visible." + (setq frame (or frame corfu-popupinfo--frame)) + (and (frame-live-p frame) (frame-visible-p frame))) + +(defun corfu-popupinfo--get-location (candidate) + "Get source at location of CANDIDATE." + (save-excursion + (let ((old-buffers (buffer-list)) (buffer nil)) + (unwind-protect + (when-let + ((extra (nth 4 completion-in-region--data)) + (fun (plist-get extra :company-location)) + ;; BUG: company-location may throw errors if location is not found + (loc (ignore-errors (funcall fun candidate))) + ((setq buffer + (or (and (bufferp (car loc)) (car loc)) + (get-file-buffer (car loc)) + (let ((inhibit-message t) + (message-log-max nil) + (inhibit-redisplay t) + (enable-dir-local-variables nil) + (enable-local-variables :safe) + (non-essential t) + (delay-mode-hooks t) + (find-file-hook '(global-font-lock-mode-check-buffers))) + (find-file-noselect (car loc) t)))))) + (with-current-buffer buffer + (save-excursion + (without-restriction + (goto-char (point-min)) + (when-let ((pos (cdr loc))) + (if (bufferp (car loc)) + (goto-char pos) + (forward-line (1- pos)))) + (let ((beg (point))) + ;; Support a little bit of scrolling. + (forward-line (* 10 corfu-popupinfo-max-height)) + (when jit-lock-mode + (jit-lock-fontify-now beg (point))) + (let ((res (buffer-substring beg (point)))) + (and (not (string-blank-p res)) res))))))) + (when (and buffer (not (memq buffer old-buffers))) + (kill-buffer buffer)))))) + +(defun corfu-popupinfo--get-documentation (candidate) + "Get the documentation for CANDIDATE." + (when-let ((extra (nth 4 completion-in-region--data)) + (fun (plist-get extra :company-doc-buffer)) + (res (save-excursion + (let ((inhibit-message t) + (message-log-max nil) + (inhibit-redisplay t) + ;; Reduce print length for elisp backend (#249) + (print-level 3) + (print-length (* corfu-popupinfo-max-width + corfu-popupinfo-max-height))) + (funcall fun candidate))))) + (with-current-buffer (or (car-safe res) res) + (setq res (string-trim + (replace-regexp-in-string + "[\n\t ]*\\[back\\][\n\t ]*" "" + (buffer-string)))) + (and (not (string-blank-p res)) res)))) + +(defun corfu-popupinfo--size () + "Return popup size as pair." + (let* ((cw (default-font-width)) + (lh (default-line-height)) + (margin + (* cw (+ (alist-get 'left-margin-width corfu-popupinfo--buffer-parameters) + (alist-get 'right-margin-width corfu-popupinfo--buffer-parameters)))) + (max-height (* lh corfu-popupinfo-max-height)) + (max-width (* cw corfu-popupinfo-max-width))) + (or (when corfu-popupinfo-resize + (with-current-buffer " *corfu-popupinfo*" + (cl-letf* (((window-dedicated-p) nil) + ((window-buffer) (current-buffer)) + (size (window-text-pixel-size + nil (point-min) (point-max) + ;; Use 3*max-height as y-limit, to take more text + ;; into account. + max-width (* 3 max-height)))) + ;; Check that width is not exceeded. Otherwise use full height, + ;; since lines will get wrapped. + (when (<= (car size) max-width) + (cons (+ margin (car size)) + ;; XXX HACK: Ensure that popup has at least a height of 1, + ;; which is the minimum frame height (#261). Maybe we + ;; should ask upstream how smaller frames can be created. + ;; I only managed to create smaller frames by setting + ;; `window-safe-min-height' to 0, which feels problematic. + (min (max (cdr size) lh) max-height)))))) + (cons (+ margin max-width) max-height)))) + +(defun corfu-popupinfo--frame-geometry (frame) + "Return position and size geometric attributes of FRAME. + +The geometry represents the position and size in pixels +in the form of (X Y WIDTH HEIGHT)." + (pcase-let ((`(,x . ,y) (frame-position frame))) + (list x y (frame-pixel-width frame) (frame-pixel-height frame)))) + +(defun corfu-popupinfo--fits-p (size area) + "Check if SIZE fits into the AREA. + +SIZE is in the form (WIDTH . HEIGHT). +AREA is in the form (X Y WIDTH HEIGHT DIR)." + (and (>= (nth 2 area) (car size)) (>= (nth 3 area) (cdr size)))) + +(defun corfu-popupinfo--larger-p (area1 area2) + "Check if AREA1 is larger than AREA2. + +AREA1 and AREA2 are both in the form (X Y WIDTH HEIGHT DIR)." + (>= (* (nth 2 area1) (nth 3 area1)) (* (nth 2 area2) (nth 3 area2)))) + +(defun corfu-popupinfo--area (ps) + "Calculate the display area for the info popup. + +PS is the pixel size of the popup. The calculated area is in the +form (X Y WIDTH HEIGHT DIR)." + (pcase-let* + ((cw (default-font-width)) + (lh (default-line-height)) + (border (alist-get 'internal-border-width corfu--frame-parameters)) + (`(,_pfx ,_pfy ,pfw ,pfh) + (corfu-popupinfo--frame-geometry (frame-parent corfu--frame))) + (`(,cfx ,cfy ,cfw ,cfh) (corfu-popupinfo--frame-geometry corfu--frame)) + ;; Candidates popup below input + (below (>= cfy (+ lh (cadr (window-inside-pixel-edges)) + (window-tab-line-height) + (or (cdr (posn-x-y (posn-at-point (point)))) 0)))) + ;; Popups aligned at top + (top-aligned (or below (< (cdr ps) cfh))) + ;; Left display area + (ahy (if top-aligned + cfy + (max 0 (- (+ cfy cfh) border border (cdr ps))))) + (ahh (if top-aligned + (min (- pfh cfy) (cdr ps)) + (min (- (+ cfy cfh) border border) (cdr ps)))) + (al (list (max 0 (- cfx (car ps) border)) ahy + (min (- cfx border) (car ps)) ahh 'left)) + ;; Right display area + (arx (+ cfx cfw (- border))) + (ar (list arx ahy (min (- pfw arx border border) (car ps)) ahh 'right)) + ;; Vertical display area + (avw (min (car ps) (- pfw cfx border border))) + (av (if below + (list cfx (+ cfy cfh (- border)) avw (min (- pfh cfy cfh border) (cdr ps)) 'vertical) + (let ((h (min (- cfy border border) (cdr ps)))) + (list cfx (max 0 (- cfy h border)) avw h 'vertical))))) + (unless (and corfu-popupinfo--lock-dir + (corfu-popupinfo--fits-p + (cons (* cw corfu-popupinfo-min-width) (* lh corfu-popupinfo-min-height)) + (pcase corfu-popupinfo--lock-dir ('left al) ('right ar) ('vertical av)))) + (setq corfu-popupinfo--lock-dir nil)) + (or + (cl-loop for dir in corfu-popupinfo-direction thereis + (pcase dir + ((or 'force-right (guard (eq corfu-popupinfo--lock-dir 'right))) ar) + ((or 'force-left (guard (eq corfu-popupinfo--lock-dir 'left))) al) + ((or 'force-vertical (guard (eq corfu-popupinfo--lock-dir 'vertical))) av) + ((and 'right (guard (corfu-popupinfo--fits-p ps ar))) ar) + ((and 'left (guard (corfu-popupinfo--fits-p ps al))) al) + ((and 'vertical (guard (corfu-popupinfo--fits-p ps av))) av))) + (let ((ah (if (corfu-popupinfo--larger-p ar al) ar al))) + (if (corfu-popupinfo--larger-p av ah) av ah))))) + +(defun corfu-popupinfo--show (candidate) + "Show the info popup for CANDIDATE." + (when corfu-popupinfo--timer + (cancel-timer corfu-popupinfo--timer) + (setq corfu-popupinfo--timer nil)) + (when (and (corfu-popupinfo--visible-p corfu--frame)) + (let* ((cand-changed + (not (and (corfu-popupinfo--visible-p) + (equal candidate corfu-popupinfo--candidate)))) + (new-coords (frame-edges corfu--frame 'inner-edges)) + (coords-changed (not (equal new-coords corfu-popupinfo--coordinates)))) + (when cand-changed + (if-let ((content (funcall corfu-popupinfo--function candidate))) + (with-current-buffer (corfu--make-buffer " *corfu-popupinfo*") + (with-silent-modifications + (erase-buffer) + (insert content) + (goto-char (point-min))) + (dolist (var corfu-popupinfo--buffer-parameters) + (set (make-local-variable (car var)) (cdr var))) + (when-let ((m (memq 'corfu-default (alist-get 'default face-remapping-alist)))) + (setcar m 'corfu-popupinfo))) + (corfu-popupinfo--hide) + (setq cand-changed nil coords-changed nil))) + (when (or cand-changed coords-changed) + (pcase-let* ((border (alist-get 'internal-border-width corfu--frame-parameters)) + (`(,area-x ,area-y ,area-w ,area-h ,area-d) + (corfu-popupinfo--area + (if cand-changed + (corfu-popupinfo--size) + (cons + (- (frame-pixel-width corfu-popupinfo--frame) border border) + (- (frame-pixel-height corfu-popupinfo--frame) border border))))) + (margin-quirk (not corfu-popupinfo--frame))) + (setq corfu-popupinfo--frame + (corfu--make-frame corfu-popupinfo--frame + area-x area-y area-w area-h + " *corfu-popupinfo*") + corfu-popupinfo--toggle t + corfu-popupinfo--lock-dir area-d + corfu-popupinfo--candidate candidate + corfu-popupinfo--coordinates new-coords) + ;; XXX HACK: Force margin update. For some reason, the call to + ;; `set-window-buffer' in `corfu--make-frame' is not effective the + ;; first time. Why does Emacs have all these quirks? + (when margin-quirk + (set-window-buffer + (frame-root-window corfu-popupinfo--frame) + " *corfu-popupinfo*"))))))) + +(defun corfu-popupinfo--hide () + "Clear the info popup buffer content and hide it." + (corfu--hide-frame corfu-popupinfo--frame)) + +(defun corfu-popupinfo-end (&optional n) + "Scroll text of info popup window to its end. + +If arg N is omitted or nil, scroll to end. If a numerical value, +put point N/10 of the way from the end. If the info popup is not +visible, the other window is moved to beginning or end." + (interactive "P") + (if (corfu-popupinfo--visible-p) + (with-selected-frame corfu-popupinfo--frame + (with-current-buffer " *corfu-popupinfo*" + (with-no-warnings + (end-of-buffer n)))) + (end-of-buffer-other-window n))) + +(defun corfu-popupinfo-beginning (&optional n) + "Scroll text of info popup window to beginning of buffer. + +See `corfu-popupinfo-end' for the argument N." + (interactive "P") + (corfu-popupinfo-end (- 10 (if (numberp n) n 0)))) + +(defun corfu-popupinfo-scroll-up (&optional n) + "Scroll text of info popup window upward N lines. + +If ARG is omitted or nil, scroll upward by a near full screen. +See `scroll-up' for details. If the info popup is not visible, +the other window is scrolled." + (interactive "p") + (if (corfu-popupinfo--visible-p) + (with-selected-frame corfu-popupinfo--frame + (with-current-buffer " *corfu-popupinfo*" + (scroll-up n))) + (scroll-other-window n))) + +(defun corfu-popupinfo-scroll-down (&optional n) + "Scroll text of info popup window down N lines. + +See `corfu-popupinfo-scroll-up' for more details." + (interactive "p") + (corfu-popupinfo-scroll-up (- (or n 1)))) + +(defun corfu-popupinfo--toggle (fun) + "Set documentation getter FUN and toggle popup." + (when (< corfu--index 0) + (corfu-popupinfo--hide) + (user-error "No candidate selected")) + (setq corfu-popupinfo--toggle + (not (and (corfu-popupinfo--visible-p) + (eq corfu-popupinfo--function fun)))) + (if (not corfu-popupinfo--toggle) + (corfu-popupinfo--hide) + (setq corfu-popupinfo--function fun + corfu-popupinfo--candidate nil) + (let ((cand (nth corfu--index corfu--candidates))) + (corfu-popupinfo--show cand) + (unless (corfu-popupinfo--visible-p) + (user-error "No %s available for `%s'" + (car (last (split-string (symbol-name fun) "-+"))) + cand))))) + +(defun corfu-popupinfo-documentation () + "Show or hide documentation in popup. +Behaves like `corfu-popupinfo-toggle'." + (interactive) + (corfu-popupinfo--toggle #'corfu-popupinfo--get-documentation)) + +(defun corfu-popupinfo-location () + "Show or hide location in popup. +Behaves like `corfu-popupinfo-toggle'." + (interactive) + (corfu-popupinfo--toggle #'corfu-popupinfo--get-location)) + +(defun corfu-popupinfo-toggle () + "Toggle the info popup display or hide. + +When using this command to manually hide the info popup, it will +not be displayed until this command is called again, even if +`corfu-popupinfo-delay' is non-nil." + (interactive) + (corfu-popupinfo--toggle corfu-popupinfo--function)) + +;;;###autoload +(define-minor-mode corfu-popupinfo-mode + "Corfu info popup minor mode." + :global t :group 'corfu) + +(cl-defmethod corfu--exhibit :after (&context (corfu-popupinfo-mode (eql t)) &optional _auto) + (when completion-in-region-mode + (setf (alist-get #'corfu-popupinfo-mode minor-mode-overriding-map-alist) + corfu-popupinfo-map) + (when corfu-popupinfo--timer + (cancel-timer corfu-popupinfo--timer) + (setq corfu-popupinfo--timer nil)) + (if (and (>= corfu--index 0) (corfu-popupinfo--visible-p corfu--frame)) + (let ((cand (nth corfu--index corfu--candidates))) + (if-let ((delay (if (consp corfu-popupinfo-delay) + (funcall (if (eq corfu-popupinfo--toggle 'init) #'car #'cdr) + corfu-popupinfo-delay) + corfu-popupinfo-delay)) + (corfu-popupinfo--toggle)) + (if (or (<= delay 0) + (and (equal cand corfu-popupinfo--candidate) + (corfu-popupinfo--visible-p))) + (corfu-popupinfo--show cand) + (when (corfu-popupinfo--visible-p) + (cond + (corfu-popupinfo-hide + (corfu-popupinfo--hide)) + (corfu-popupinfo--candidate + (corfu-popupinfo--show corfu-popupinfo--candidate)))) + (setq corfu-popupinfo--timer + (run-at-time delay nil #'corfu-popupinfo--show cand))) + (unless (equal cand corfu-popupinfo--candidate) + (corfu-popupinfo--hide)))) + (corfu-popupinfo--hide)))) + +(cl-defmethod corfu--teardown :before (_buf &context (corfu-popupinfo-mode (eql t))) + (corfu-popupinfo--hide) + (cl-loop for (k . v) in corfu-popupinfo--initial-state do (set k v)) + (cl-callf2 assq-delete-all #'corfu-popupinfo-mode minor-mode-overriding-map-alist)) + +;; Emacs 28: Do not show Corfu commands with M-X +(dolist (sym '(corfu-popupinfo-scroll-down corfu-popupinfo-scroll-up + corfu-popupinfo-documentation corfu-popupinfo-location + corfu-popupinfo-beginning corfu-popupinfo-end + corfu-popupinfo-toggle)) + (put sym 'completion-predicate #'ignore)) + +(provide 'corfu-popupinfo) +;;; corfu-popupinfo.el ends here diff --git a/elpa/corfu-1.3/corfu-quick.el b/elpa/corfu-1.3/corfu-quick.el @@ -0,0 +1,154 @@ +;;; corfu-quick.el --- Quick keys for Corfu -*- lexical-binding: t -*- + +;; Copyright (C) 2022-2024 Free Software Foundation, Inc. + +;; Author: Luis Henriquez-Perez <luis@luishp.xyz>, Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2022 +;; Version: 1.3 +;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (corfu "1.3")) +;; Homepage: https://github.com/minad/corfu + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This package is a Corfu extension, which prefixes candidates with +;; quick keys. Typing these quick keys allows you to select the +;; candidate in front of them. This is designed to be a faster +;; alternative to selecting a candidate with `corfu-next' and +;; `corfu-previous'. +;; (keymap-set corfu-map "M-q" #'corfu-quick-complete) +;; (keymap-set corfu-map "C-q" #'corfu-quick-insert) + +;;; Code: + +(require 'corfu) +(eval-when-compile + (require 'cl-lib)) + +(defcustom corfu-quick1 "asdfgh" + "First level quick keys." + :type 'string + :group 'corfu) + +(defcustom corfu-quick2 "jkluionm" + "Second level quick keys." + :type 'string + :group 'corfu) + +(defface corfu-quick1 + '((((class color) (min-colors 88) (background dark)) + :background "#0050af" :foreground "white" :inherit bold) + (((class color) (min-colors 88) (background light)) + :background "#7feaff" :foreground "black" :inherit bold) + (t :background "blue" :foreground "white" :inherit bold)) + "Face used for the first quick key." + :group 'corfu-faces) + +(defface corfu-quick2 + '((((class color) (min-colors 88) (background dark)) + :background "#7f1f7f" :foreground "white" :inherit bold) + (((class color) (min-colors 88) (background light)) + :background "#ffaaff" :foreground "black" :inherit bold) + (t :background "magenta" :foreground "white" :inherit bold)) + "Face used for the second quick key." + :group 'corfu-faces) + +(defun corfu-quick--keys (two idx) ;; See vertico-quick--keys + "Format quick keys prefix. +IDX is the current candidate index. +TWO is non-nil if two keys should be displayed." + (let ((fst (length corfu-quick1)) + (snd (length corfu-quick2))) + (if (>= idx fst) + (let ((first (elt corfu-quick2 (mod (/ (- idx fst) fst) snd))) + (second (elt corfu-quick1 (mod (- idx fst) fst)))) + (cond + ((eq first two) + (list + (concat " " (propertize (char-to-string second) 'face 'corfu-quick1)) + (cons second (+ corfu--scroll idx)))) + (two + (list " ")) + (t + (list + (concat (propertize (char-to-string first) 'face 'corfu-quick1) + (propertize (char-to-string second) 'face 'corfu-quick2)) + (cons first (list first)))))) + (let ((first (elt corfu-quick1 (mod idx fst)))) + (if two + (list " ") + (list + (concat (propertize (char-to-string first) 'face 'corfu-quick1) " ") + (cons first (+ corfu--scroll idx)))))))) + +(defun corfu-quick--read (&optional first) + "Read quick key given FIRST pressed key." + (cl-letf* ((list nil) + (space1 (propertize " " 'display + `(space :width + (+ 0.5 (,(alist-get + 'child-frame-border-width + corfu--frame-parameters)))))) + (space2 #(" " 0 1 (display (space :width 0.5)))) + (orig (symbol-function #'corfu--affixate)) + ((symbol-function #'corfu--affixate) + (lambda (cands) + (setq cands (cdr (funcall orig cands))) + (cl-loop for cand in cands for index from 0 do + (pcase-let ((`(,keys . ,events) (corfu-quick--keys first index))) + (setq list (nconc events list)) + (setf (cadr cand) (concat space1 (propertize " " 'display keys) space2)))) + (cons t cands))) + ;; Increase minimum width to avoid odd jumping + (corfu-min-width (+ 3 corfu-min-width))) + (corfu--candidates-popup + (posn-at-point (+ (car completion-in-region--data) (length corfu--base)))) + (alist-get (read-key) list))) + +;;;###autoload +(defun corfu-quick-jump () + "Jump to candidate using quick keys." + (interactive) + (when (fboundp 'corfu-echo--cancel) + (corfu-echo--cancel)) + (if (= corfu--total 0) + (and (message "No match") nil) + (let ((idx (corfu-quick--read))) + (when (consp idx) (setq idx (corfu-quick--read (car idx)))) + (when idx (setq corfu--index idx))))) + +;;;###autoload +(defun corfu-quick-insert () + "Insert candidate using quick keys." + (interactive) + (when (corfu-quick-jump) + (corfu-insert))) + +;;;###autoload +(defun corfu-quick-complete () + "Complete candidate using quick keys." + (interactive) + (when (corfu-quick-jump) + (corfu-complete))) + +;; Emacs 28: Do not show Corfu commands in M-X +(dolist (sym '(corfu-quick-jump corfu-quick-insert corfu-quick-complete)) + (put sym 'completion-predicate #'ignore)) + +(provide 'corfu-quick) +;;; corfu-quick.el ends here diff --git a/elpa/corfu-1.3/corfu.el b/elpa/corfu-1.3/corfu.el @@ -0,0 +1,1398 @@ +;;; corfu.el --- COmpletion in Region FUnction -*- lexical-binding: t -*- + +;; Copyright (C) 2021-2024 Free Software Foundation, Inc. + +;; Author: Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2021 +;; Version: 1.3 +;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4")) +;; Homepage: https://github.com/minad/corfu +;; Keywords: abbrev, convenience, matching, completion, text + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Corfu enhances in-buffer completion with a small completion popup. +;; The current candidates are shown in a popup below or above the +;; point. The candidates can be selected by moving up and down. +;; Corfu is the minimalistic in-buffer completion counterpart of the +;; Vertico minibuffer UI. + +;;; Code: + +(require 'compat) +(eval-when-compile + (require 'cl-lib) + (require 'subr-x)) + +(defgroup corfu nil + "COmpletion in Region FUnction." + :link '(info-link :tag "Info Manual" "(corfu)") + :link '(url-link :tag "Homepage" "https://github.com/minad/corfu") + :link '(emacs-library-link :tag "Library Source" "corfu.el") + :group 'convenience + :group 'tools + :group 'matching + :prefix "corfu-") + +(defcustom corfu-count 10 + "Maximal number of candidates to show." + :type 'natnum) + +(defcustom corfu-scroll-margin 2 + "Number of lines at the top and bottom when scrolling. +The value should lie between 0 and corfu-count/2." + :type 'natnum) + +(defcustom corfu-min-width 15 + "Popup minimum width in characters." + :type 'natnum) + +(defcustom corfu-max-width 100 + "Popup maximum width in characters." + :type 'natnum) + +(defcustom corfu-cycle nil + "Enable cycling for `corfu-next' and `corfu-previous'." + :type 'boolean) + +(defcustom corfu-on-exact-match 'insert + "Configure how a single exact match should be handled. +- nil: No special handling, continue completion. +- insert: Insert candidate, quit and call the `:exit-function'. +- quit: Quit completion without further action. +- show: Initiate completion even for a single match only." + :type '(choice (const insert) (const show) (const quit) (const nil))) + +(defcustom corfu-continue-commands + ;; nil is undefined command + '(nil ignore universal-argument universal-argument-more digit-argument + "\\`corfu-" "\\`scroll-other-window") + "Continue Corfu completion after executing these commands. +The list can container either command symbols or regular expressions." + :type '(repeat (choice regexp symbol))) + +(defcustom corfu-preview-current 'insert + "Preview currently selected candidate. +If the variable has the value `insert', the candidate is automatically +inserted on further input." + :type '(choice boolean (const insert))) + +(defcustom corfu-preselect 'valid + "Configure if the prompt or first candidate is preselected. +- prompt: Always select the prompt. +- first: Always select the first candidate. +- valid: Only select the prompt if valid and not equal to the first candidate. +- directory: Like first, but select the prompt if it is a directory." + :type '(choice (const prompt) (const valid) (const first) (const directory))) + +(defcustom corfu-separator ?\s + "Component separator character. +The character used for separating components in the input. The presence +of this separator character will inhibit quitting at completion +boundaries, so that any further characters can be entered. To enter the +first separator character, call `corfu-insert-separator' (bound to M-SPC +by default). Useful for multi-component completion styles such as +Orderless." + :type 'character) + +(defcustom corfu-quit-at-boundary 'separator + "Automatically quit at completion boundary. +nil: Never quit at completion boundary. +t: Always quit at completion boundary. +separator: Quit at boundary if no `corfu-separator' has been inserted." + :type '(choice boolean (const separator))) + +(defcustom corfu-quit-no-match 'separator + "Automatically quit if no matching candidate is found. +When staying alive even if there is no match a warning message is +shown in the popup. +nil: Stay alive even if there is no match. +t: Quit if there is no match. +separator: Only stay alive if there is no match and +`corfu-separator' has been inserted." + :type '(choice boolean (const separator))) + +(defcustom corfu-left-margin-width 0.5 + "Width of the left margin in units of the character width." + :type 'float) + +(defcustom corfu-right-margin-width 0.5 + "Width of the right margin in units of the character width." + :type 'float) + +(defcustom corfu-bar-width 0.2 + "Width of the bar in units of the character width." + :type 'float) + +(defcustom corfu-margin-formatters nil + "Registry for margin formatter functions. +Each function of the list is called with the completion metadata as +argument until an appropriate formatter is found. The function should +return a formatter function, which takes the candidate string and must +return a string, possibly an icon." + :type 'hook) + +(defcustom corfu-sort-function #'corfu-sort-length-alpha + "Default sorting function. +This function is used if the completion table does not specify a +`display-sort-function'." + :type `(choice + (const :tag "No sorting" nil) + (const :tag "By length and alpha" ,#'corfu-sort-length-alpha) + (function :tag "Custom function"))) + +(defcustom corfu-sort-override-function nil + "Override sort function which overrides the `display-sort-function'. +This function is used even if a completion table specifies its +own sort function." + :type '(choice (const nil) function)) + +(defcustom corfu-auto-prefix 3 + "Minimum length of prefix for auto completion. +The completion backend can override this with +:company-prefix-length. It is *not recommended* to use a small +prefix length (below 2), since this will create high load for +Emacs. See also `corfu-auto-delay'." + :type 'natnum) + +(defcustom corfu-auto-delay 0.2 + "Delay for auto completion. +It is *not recommended* to use a short delay or even 0, since +this will create high load for Emacs, in particular if executing +the completion backend is costly." + :type 'float) + +(defcustom corfu-auto-commands + '("self-insert-command\\'" + c-electric-colon c-electric-lt-gt c-electric-slash c-scope-operator) + "Commands which initiate auto completion. +The list can container either command symbols or regular expressions." + :type '(repeat (choice regexp symbol))) + +(defcustom corfu-auto nil + "Enable auto completion. +See also the settings `corfu-auto-delay', `corfu-auto-prefix' and +`corfu-auto-commands'." + :type 'boolean) + +(defgroup corfu-faces nil + "Faces used by Corfu." + :group 'corfu + :group 'faces) + +(defface corfu-default + '((((class color) (min-colors 88) (background dark)) :background "#191a1b") + (((class color) (min-colors 88) (background light)) :background "#f0f0f0") + (t :background "gray")) + "Default face, foreground and background colors used for the popup.") + +(defface corfu-current + '((((class color) (min-colors 88) (background dark)) + :background "#00415e" :foreground "white") + (((class color) (min-colors 88) (background light)) + :background "#c0efff" :foreground "black") + (t :background "blue" :foreground "white")) + "Face used to highlight the currently selected candidate.") + +(defface corfu-bar + '((((class color) (min-colors 88) (background dark)) :background "#a8a8a8") + (((class color) (min-colors 88) (background light)) :background "#505050") + (t :background "gray")) + "The background color is used for the scrollbar indicator.") + +(defface corfu-border + '((((class color) (min-colors 88) (background dark)) :background "#323232") + (((class color) (min-colors 88) (background light)) :background "#d7d7d7") + (t :background "gray")) + "The background color used for the thin border.") + +(defface corfu-annotations + '((t :inherit completions-annotations)) + "Face used for annotations.") + +(defface corfu-deprecated + '((t :inherit shadow :strike-through t)) + "Face used for deprecated candidates.") + +(defvar-keymap corfu-mode-map + :doc "Keymap used when `corfu-mode' is active.") + +(defvar-keymap corfu-map + :doc "Keymap used when popup is shown." + "<remap> <move-beginning-of-line>" #'corfu-prompt-beginning + "<remap> <move-end-of-line>" #'corfu-prompt-end + "<remap> <beginning-of-buffer>" #'corfu-first + "<remap> <end-of-buffer>" #'corfu-last + "<remap> <scroll-down-command>" #'corfu-scroll-down + "<remap> <scroll-up-command>" #'corfu-scroll-up + "<remap> <next-line>" #'corfu-next + "<remap> <previous-line>" #'corfu-previous + "<remap> <completion-at-point>" #'corfu-complete + "<remap> <keyboard-escape-quit>" #'corfu-reset + "<down>" #'corfu-next + "<up>" #'corfu-previous + ;; XXX C-a is bound because of Eshell. + ;; Ideally Eshell would remap move-beginning-of-line. + "C-a" #'corfu-prompt-beginning + ;; XXX [tab] is bound because of org-mode and orgtbl-mode. + ;; The binding should be removed from org-mode-map. + "<tab>" #'corfu-complete + "M-n" #'corfu-next + "M-p" #'corfu-previous + "C-g" #'corfu-quit + "RET" #'corfu-insert + "TAB" #'corfu-complete + "M-TAB" #'corfu-expand + "M-g" 'corfu-info-location + "M-h" 'corfu-info-documentation + "M-SPC" #'corfu-insert-separator) + +(defvar corfu--auto-timer (timer-create) + "Auto completion timer.") + +(defvar corfu--candidates nil + "List of candidates.") + +(defvar corfu--metadata nil + "Completion metadata.") + +(defvar corfu--base "" + "Base string, which is concatenated with the candidate.") + +(defvar corfu--total 0 + "Length of the candidate list `corfu--candidates'.") + +(defvar corfu--hilit #'identity + "Lazy candidate highlighting function.") + +(defvar corfu--index -1 + "Index of current candidate or negative for prompt selection.") + +(defvar corfu--preselect -1 + "Index of preselected candidate, negative for prompt selection.") + +(defvar corfu--scroll 0 + "Scroll position.") + +(defvar corfu--input nil + "Cons of last prompt contents and point.") + +(defvar corfu--preview-ov nil + "Current candidate overlay.") + +(defvar corfu--change-group nil + "Undo change group.") + +(defvar corfu--frame nil + "Popup frame.") + +(defconst corfu--initial-state + (mapcar + (lambda (k) (cons k (symbol-value k))) + '(corfu--base + corfu--candidates + corfu--hilit + corfu--index + corfu--preselect + corfu--scroll + corfu--input + corfu--total + corfu--preview-ov + corfu--change-group + corfu--metadata)) + "Initial Corfu state.") + +(defvar corfu--frame-parameters + '((no-accept-focus . t) + (no-focus-on-map . t) + (min-width . t) + (min-height . t) + (border-width . 0) + (outer-border-width . 0) + (internal-border-width . 1) + (child-frame-border-width . 1) + (left-fringe . 0) + (right-fringe . 0) + (vertical-scroll-bars . nil) + (horizontal-scroll-bars . nil) + (menu-bar-lines . 0) + (tool-bar-lines . 0) + (tab-bar-lines . 0) + (no-other-frame . t) + (unsplittable . t) + (undecorated . t) + (cursor-type . nil) + (no-special-glyphs . t) + (desktop-dont-save . t)) + "Default child frame parameters.") + +(defvar corfu--buffer-parameters + '((mode-line-format . nil) + (header-line-format . nil) + (tab-line-format . nil) + (tab-bar-format . nil) ;; Emacs 28 tab-bar-format + (frame-title-format . "") + (truncate-lines . t) + (cursor-in-non-selected-windows . nil) + (cursor-type . nil) + (show-trailing-whitespace . nil) + (display-line-numbers . nil) + (left-fringe-width . nil) + (right-fringe-width . nil) + (left-margin-width . 0) + (right-margin-width . 0) + (fringes-outside-margins . 0) + (fringe-indicator-alist . nil) + (indicate-empty-lines . nil) + (indicate-buffer-boundaries . nil) + (buffer-read-only . t)) + "Default child frame buffer parameters.") + +(defvar corfu--mouse-ignore-map + (let ((map (make-sparse-keymap))) + (dotimes (i 7) + (dolist (k '(mouse down-mouse drag-mouse double-mouse triple-mouse)) + (keymap-set map (format "<%s-%s>" k (1+ i)) #'ignore))) + map) + "Ignore all mouse clicks.") + +(defun corfu--replace (beg end str) + "Replace range between BEG and END with STR." + (unless (equal str (buffer-substring-no-properties beg end)) + ;; bug#55205: completion--replace removed properties as an unwanted + ;; side-effect. We also don't want to leave text properties. + (completion--replace beg end (substring-no-properties str)))) + +(defun corfu--capf-wrapper (fun &optional prefix) + "Wrapper for `completion-at-point' FUN. +The wrapper determines if the Capf is applicable at the current +position and performs sanity checking on the returned result. +For non-exclusive Capfs wrapper additionally checks if the +current input can be completed successfully. PREFIX is a prefix +length override, set to t for manual completion." + (pcase (funcall fun) + ((and res `(,beg ,end ,table . ,plist)) + (and (integer-or-marker-p beg) ;; Valid Capf result + (<= beg (point) end) ;; Sanity checking + ;; When auto completing, check the prefix length! + (let ((len (or prefix + (plist-get plist :company-prefix-length) + (- (point) beg)))) + (or (eq len t) (>= len corfu-auto-prefix))) + ;; For non-exclusive Capfs, check for valid completion. + (or (not (eq 'no (plist-get plist :exclusive))) + (let* ((str (buffer-substring-no-properties beg end)) + (pt (- (point) beg)) + (pred (plist-get plist :predicate)) + (md (completion-metadata (substring str 0 pt) table pred))) + ;; We use `completion-try-completion' to check if there are + ;; completions. The upstream `completion--capf-wrapper' uses + ;; `try-completion' which is incorrect since it only checks for + ;; prefix completions. + (completion-try-completion str table pred pt md))) + (cons fun res))))) + +(defun corfu--make-buffer (name) + "Create buffer with NAME." + (let ((fr face-remapping-alist) + (ls line-spacing) + (buffer (get-buffer-create name))) + (with-current-buffer buffer + ;;; XXX HACK install mouse ignore map + (use-local-map corfu--mouse-ignore-map) + (dolist (var corfu--buffer-parameters) + (set (make-local-variable (car var)) (cdr var))) + (setq-local face-remapping-alist (copy-tree fr) + line-spacing ls) + (cl-pushnew 'corfu-default (alist-get 'default face-remapping-alist)) + buffer))) + +(defvar x-gtk-resize-child-frames) ;; Not present on non-gtk builds +(defvar corfu--gtk-resize-child-frames + (let ((case-fold-search t)) + ;; XXX HACK to fix resizing on gtk3/gnome taken from posframe.el + ;; More information: + ;; * https://github.com/minad/corfu/issues/17 + ;; * https://gitlab.gnome.org/GNOME/mutter/-/issues/840 + ;; * https://lists.gnu.org/archive/html/emacs-devel/2020-02/msg00001.html + (and (string-match-p "gtk3" system-configuration-features) + (string-match-p "gnome\\|cinnamon" + (or (getenv "XDG_CURRENT_DESKTOP") + (getenv "DESKTOP_SESSION") "")) + 'resize-mode))) + +;; Function adapted from posframe.el by tumashu +(defun corfu--make-frame (frame x y width height buffer) + "Show BUFFER in child frame at X/Y with WIDTH/HEIGHT. +FRAME is the existing frame." + (when-let (((frame-live-p frame)) + (timer (frame-parameter frame 'corfu--hide-timer))) + (cancel-timer timer) + (set-frame-parameter frame 'corfu--hide-timer nil)) + (let* ((window-min-height 1) + (window-min-width 1) + (inhibit-redisplay t) + (x-gtk-resize-child-frames corfu--gtk-resize-child-frames) + (before-make-frame-hook) + (after-make-frame-functions) + (parent (window-frame))) + (unless (and (frame-live-p frame) + (eq (frame-parent frame) + (and (not (bound-and-true-p exwm--connection)) parent)) + ;; If there is more than one window, `frame-root-window' may + ;; return nil. Recreate the frame in this case. + (window-live-p (frame-root-window frame))) + (when frame (delete-frame frame)) + (setq frame (make-frame + `((parent-frame . ,parent) + (minibuffer . ,(minibuffer-window parent)) + (width . 0) (height . 0) (visibility . nil) + ,@corfu--frame-parameters)))) + ;; XXX HACK Setting the same frame-parameter/face-background is not a nop. + ;; Check before applying the setting. Without the check, the frame flickers + ;; on Mac. We have to apply the face background before adjusting the frame + ;; parameter, otherwise the border is not updated. + (let ((new (face-attribute 'corfu-border :background nil 'default))) + (unless (equal (face-attribute 'internal-border :background frame 'default) new) + (set-face-background 'internal-border new frame)) + ;; XXX The Emacs Mac Port does not support `internal-border', we also have + ;; to set `child-frame-border'. + (unless (or (not (facep 'child-frame-border)) + (equal (face-attribute 'child-frame-border :background frame 'default) new)) + (set-face-background 'child-frame-border new frame))) + ;; Reset frame parameters if they changed. For example `tool-bar-mode' + ;; overrides the parameter `tool-bar-lines' for every frame, including child + ;; frames. The child frame API is a pleasure to work with. It is full of + ;; lovely surprises. + (let* ((is (frame-parameters frame)) + (should `((background-color + . ,(face-attribute 'corfu-default :background nil 'default)) + (font . ,(frame-parameter parent 'font)) + ,@corfu--frame-parameters)) + (diff (cl-loop for p in should for (k . v) = p + unless (equal (alist-get k is) v) collect p))) + (when diff (modify-frame-parameters frame diff))) + (let ((win (frame-root-window frame))) + (unless (eq (window-buffer win) buffer) + (set-window-buffer win buffer)) + ;; Disallow selection of root window (gh:minad/corfu#63) + (set-window-parameter win 'no-delete-other-windows t) + (set-window-parameter win 'no-other-window t) + ;; Mark window as dedicated to prevent frame reuse (gh:minad/corfu#60) + (set-window-dedicated-p win t)) + (redirect-frame-focus frame parent) + (set-frame-size frame width height t) + (pcase-let ((`(,px . ,py) (frame-position frame))) + (unless (and (= x px) (= y py)) + (set-frame-position frame x y)))) + (make-frame-visible frame) + ;; Unparent child frame if EXWM is used, otherwise EXWM buffers are drawn on + ;; top of the Corfu child frame. + (when (and (bound-and-true-p exwm--connection) (frame-parent frame)) + (set-frame-parameter frame 'parent-frame nil)) + frame) + +(defun corfu--hide-frame-deferred (frame) + "Deferred hiding of child FRAME." + (when (and (frame-live-p frame) (frame-visible-p frame)) + (set-frame-parameter frame 'corfu--hide-timer nil) + (make-frame-invisible frame) + (with-current-buffer (window-buffer (frame-root-window frame)) + (with-silent-modifications + (erase-buffer))))) + +(defun corfu--hide-frame (frame) + "Hide child FRAME." + (when (and (frame-live-p frame) (frame-visible-p frame) + (not (frame-parameter frame 'corfu--hide-timer))) + (set-frame-parameter frame 'corfu--hide-timer + (run-at-time 0 nil #'corfu--hide-frame-deferred frame)))) + +(defun corfu--move-to-front (elem list) + "Move ELEM to front of LIST." + ;; In contrast to Vertico, this function handles duplicates. See also the + ;; special deduplication function `corfu--delete-dups' based on + ;; `equal-including-properties' + (nconc (cl-loop for x in list if (equal x elem) collect x) + (delete elem list))) + +(defun corfu--filter-completions (&rest args) + "Compute all completions for ARGS with lazy highlighting." + (defvar completion-lazy-hilit) + (defvar completion-lazy-hilit-fn) + (cl-letf* ((completion-lazy-hilit t) + (completion-lazy-hilit-fn nil) + ((symbol-function #'completion-hilit-commonality) + (lambda (cands prefix &optional base) + (setq completion-lazy-hilit-fn + (lambda (x) (car (completion-hilit-commonality (list x) prefix base)))) + (and cands (nconc cands base))))) + (if (eval-when-compile (>= emacs-major-version 30)) + (cons (apply #'completion-all-completions args) completion-lazy-hilit-fn) + (cl-letf* ((orig-pcm (symbol-function #'completion-pcm--hilit-commonality)) + (orig-flex (symbol-function #'completion-flex-all-completions)) + ((symbol-function #'completion-flex-all-completions) + (lambda (&rest args) + ;; Unfortunately for flex we have to undo the lazy highlighting, since flex uses + ;; the completion-score for sorting, which is applied during highlighting. + (cl-letf (((symbol-function #'completion-pcm--hilit-commonality) orig-pcm)) + (apply orig-flex args)))) + ((symbol-function #'completion-pcm--hilit-commonality) + (lambda (pattern cands) + (setq completion-lazy-hilit-fn + (lambda (x) + ;; `completion-pcm--hilit-commonality' sometimes throws an internal error + ;; for example when entering "/sudo:://u". + (condition-case nil + (car (completion-pcm--hilit-commonality pattern (list x))) + (t x)))) + cands))) + (cons (apply #'completion-all-completions args) completion-lazy-hilit-fn))))) + +(defsubst corfu--length-string< (x y) + "Sorting predicate which compares X and Y first by length then by `string<'." + (or (< (length x) (length y)) (and (= (length x) (length y)) (string< x y)))) + +(defmacro corfu--partition! (list form) + "Evaluate FORM for every element and partition LIST." + (cl-with-gensyms (head1 head2 tail1 tail2) + `(let* ((,head1 (cons nil nil)) + (,head2 (cons nil nil)) + (,tail1 ,head1) + (,tail2 ,head2)) + (while ,list + (if (let ((it (car ,list))) ,form) + (progn + (setcdr ,tail1 ,list) + (pop ,tail1)) + (setcdr ,tail2 ,list) + (pop ,tail2)) + (pop ,list)) + (setcdr ,tail1 (cdr ,head2)) + (setcdr ,tail2 nil) + (setq ,list (cdr ,head1))))) + +(defun corfu--move-prefix-candidates-to-front (field cands) + "Move CANDS which match prefix of FIELD to the beginning." + (let* ((word (substring field 0 + (seq-position field corfu-separator))) + (len (length word))) + (corfu--partition! + cands + (and (>= (length it) len) + (eq t (compare-strings word 0 len it 0 len + completion-ignore-case)))))) + +(defun corfu--delete-dups (list) + "Delete `equal-including-properties' consecutive duplicates from LIST." + (let ((beg list)) + (while (cdr beg) + (let ((end (cdr beg))) + (while (equal (car beg) (car end)) (pop end)) + ;; The deduplication is quadratic in the number of duplicates. We can + ;; avoid the quadratic complexity with a hash table which takes + ;; properties into account (available since Emacs 28). + (while (not (eq beg end)) + (let ((dup beg)) + (while (not (eq (cdr dup) end)) + ;; bug#6581: `equal-including-properties' uses `eq' to compare + ;; properties until 29.1. Approximate by comparing + ;; `text-properties-at' position 0. + (if (if (eval-when-compile (< emacs-major-version 29)) + (equal (text-properties-at 0 (car beg)) + (text-properties-at 0 (cadr dup))) + (equal-including-properties (car beg) (cadr dup))) + (setcdr dup (cddr dup)) + (pop dup)))) + (pop beg))))) + list) + +(defun corfu--sort-function () + "Return the sorting function." + (or corfu-sort-override-function + (corfu--metadata-get 'display-sort-function) + corfu-sort-function)) + +(defun corfu--recompute (str pt table pred) + "Recompute state from STR, PT, TABLE and PRED." + (pcase-let* ((before (substring str 0 pt)) + (after (substring str pt)) + (corfu--metadata (completion-metadata before table pred)) + ;; bug#47678: `completion-boundaries' fails for `partial-completion' + ;; if the cursor is moved between the slashes of "~//". + ;; See also vertico.el which has the same issue. + (bounds (condition-case nil + (completion-boundaries before table pred after) + (t (cons 0 (length after))))) + (field (substring str (car bounds) (+ pt (cdr bounds)))) + (completing-file (eq (corfu--metadata-get 'category) 'file)) + (`(,all . ,hl) (corfu--filter-completions str table pred pt corfu--metadata)) + (base (or (when-let ((z (last all))) (prog1 (cdr z) (setcdr z nil))) 0)) + (corfu--base (substring str 0 base)) + (pre nil)) + ;; Filter the ignored file extensions. We cannot use modified predicate for + ;; this filtering, since this breaks the special casing in the + ;; `completion-file-name-table' for `file-exists-p' and `file-directory-p'. + (when completing-file (setq all (completion-pcm--filename-try-filter all))) + ;; Sort using the `display-sort-function' or the Corfu sort functions, and + ;; delete duplicates with respect to `equal-including-properties'. This is + ;; a deviation from the Vertico completion UI with more aggressive + ;; deduplication, where candidates are compared with `equal'. Corfu + ;; preserves candidates which differ in their text properties. Corfu tries + ;; to preserve text properties as much as possible, when calling the + ;; `:exit-function' to help Capfs with candidate disambiguation. This + ;; matters in particular for Lsp backends, which produce duplicates for + ;; overloaded methods. + (setq all (corfu--delete-dups (funcall (or (corfu--sort-function) #'identity) all)) + all (corfu--move-prefix-candidates-to-front field all)) + (when (and completing-file (not (string-suffix-p "/" field))) + (setq all (corfu--move-to-front (concat field "/") all))) + (setq all (corfu--move-to-front field all) + pre (if (or (eq corfu-preselect 'prompt) (not all) + (and completing-file (eq corfu-preselect 'directory) + (= (length corfu--base) (length str)) + (test-completion str table pred)) + (and (eq corfu-preselect 'valid) + (not (equal field (car all))) + (not (and completing-file (equal (concat field "/") (car all)))) + (test-completion str table pred))) + -1 0)) + `((corfu--base . ,corfu--base) + (corfu--metadata . ,corfu--metadata) + (corfu--candidates . ,all) + (corfu--total . ,(length all)) + (corfu--hilit . ,(or hl #'identity)) + (corfu--preselect . ,pre) + (corfu--index . ,(or (and (>= corfu--index 0) (/= corfu--index corfu--preselect) + (seq-position all (nth corfu--index corfu--candidates))) + pre))))) + +(defun corfu--update (&optional interruptible) + "Update state, optionally INTERRUPTIBLE." + (pcase-let* ((`(,beg ,end ,table ,pred . ,_) completion-in-region--data) + (pt (- (point) beg)) + (str (buffer-substring-no-properties beg end)) + (input (cons str pt))) + (unless (equal corfu--input input) + ;; Redisplay such that the input is immediately shown before the expensive + ;; candidate recomputation (gh:minad/corfu#48). See also corresponding + ;; issue gh:minad/vertico#89. + (when interruptible (redisplay)) + ;; Bind non-essential=t to prevent Tramp from opening new connections, + ;; without the user explicitly requesting it via M-TAB. + (pcase (let ((non-essential t)) + ;; XXX Guard against errors during candidate generation. + ;; bug#61274: `dabbrev-capf' signals errors. + (condition-case err + (if interruptible + (while-no-input (corfu--recompute str pt table pred)) + (corfu--recompute str pt table pred)) + (error + (message "Corfu completion error: %s" (error-message-string err)) + t))) + ('nil (keyboard-quit)) + ((and state (pred consp)) + (setq corfu--input input) + (dolist (s state) (set (car s) (cdr s)))))) + input)) + +(defun corfu--match-symbol-p (pattern sym) + "Return non-nil if SYM is matching an element of the PATTERN list." + (cl-loop with case-fold-search = nil + for x in (and (symbolp sym) pattern) + thereis (if (symbolp x) + (eq sym x) + (string-match-p x (symbol-name sym))))) + +(defun corfu--metadata-get (prop) + "Return PROP from completion metadata." + ;; Note: Do not use `completion-metadata-get' in order to avoid Marginalia. + ;; The Marginalia annotators are too heavy for the Corfu popup! + (cdr (assq prop corfu--metadata))) + +(defun corfu--format-candidates (cands) + "Format annotated CANDS." + (setq cands + (cl-loop for c in cands collect + (cl-loop for s in c collect + (replace-regexp-in-string "[ \t]*\n[ \t]*" " " s)))) + (let* ((cw (cl-loop for x in cands maximize (string-width (car x)))) + (pw (cl-loop for x in cands maximize (string-width (cadr x)))) + (sw (cl-loop for x in cands maximize (string-width (caddr x)))) + (width (+ pw cw sw)) + ;; -4 because of margins and some additional safety + (max-width (min corfu-max-width (- (frame-width) 4)))) + (when (> width max-width) + (setq sw (max 0 (- max-width pw cw)) + width (+ pw cw sw))) + (when (< width corfu-min-width) + (setq cw (+ cw (- corfu-min-width width)) + width corfu-min-width)) + (setq width (min width max-width)) + (list pw width + (cl-loop for (cand prefix suffix) in cands collect + (truncate-string-to-width + (concat + prefix (make-string (max 0 (- pw (string-width prefix))) ?\s) + cand + (when (/= sw 0) + (make-string (+ (max 0 (- cw (string-width cand))) + (max 0 (- sw (string-width suffix)))) + ?\s)) + suffix) + width))))) + +(defun corfu--compute-scroll () + "Compute new scroll position." + (let ((off (max (min corfu-scroll-margin (/ corfu-count 2)) 0)) + (corr (if (= corfu-scroll-margin (/ corfu-count 2)) (1- (mod corfu-count 2)) 0))) + (setq corfu--scroll (min (max 0 (- corfu--total corfu-count)) + (max 0 (+ corfu--index off 1 (- corfu-count)) + (min (- corfu--index off corr) corfu--scroll)))))) + +(defun corfu--candidates-popup (pos) + "Show candidates popup at POS." + (corfu--compute-scroll) + (pcase-let* ((last (min (+ corfu--scroll corfu-count) corfu--total)) + (bar (ceiling (* corfu-count corfu-count) corfu--total)) + (lo (min (- corfu-count bar 1) (floor (* corfu-count corfu--scroll) corfu--total))) + (`(,mf . ,acands) (corfu--affixate + (cl-loop repeat corfu-count + for c in (nthcdr corfu--scroll corfu--candidates) + collect (funcall corfu--hilit (substring c))))) + (`(,pw ,width ,fcands) (corfu--format-candidates acands)) + ;; Disable the left margin if a margin formatter is active. + (corfu-left-margin-width (if mf 0 corfu-left-margin-width))) + ;; Nonlinearity at the end and the beginning + (when (/= corfu--scroll 0) + (setq lo (max 1 lo))) + (when (/= last corfu--total) + (setq lo (min (- corfu-count bar 2) lo))) + (corfu--popup-show pos pw width fcands (- corfu--index corfu--scroll) + (and (> corfu--total corfu-count) lo) bar))) + +(defun corfu--range-valid-p () + "Check the completion range, return non-nil if valid." + (pcase-let ((buf (current-buffer)) + (pt (point)) + (`(,beg ,end . ,_) completion-in-region--data)) + (and beg end + (eq buf (marker-buffer beg)) (eq buf (window-buffer)) + (<= beg pt end) + (save-excursion (goto-char beg) (<= (pos-bol) pt (pos-eol)))))) + +(defun corfu--continue-p () + "Check if completion should continue after a command. +Corfu bails out if the current buffer changed unexpectedly or if +point moved out of range, see `corfu--range-valid-p'. Also the +input must satisfy the `completion-in-region-mode--predicate' and +the last command must be listed in `corfu-continue-commands'." + (and (corfu--range-valid-p) + ;; We keep Corfu alive if a `overriding-terminal-local-map' is + ;; installed, e.g., the `universal-argument-map'. It would be good to + ;; think about a better criterion instead. Unfortunately relying on + ;; `this-command' alone is insufficient, since the value of + ;; `this-command' gets clobbered in the case of transient keymaps. + (or overriding-terminal-local-map + ;; Check if it is an explicitly listed continue command + (corfu--match-symbol-p corfu-continue-commands this-command) + (pcase-let ((`(,beg ,end . ,_) completion-in-region--data)) + (and (or (not corfu--input) (< beg end)) ;; Check for empty input + (or (not corfu-quit-at-boundary) ;; Check separator or predicate + (and (eq corfu-quit-at-boundary 'separator) + (or (eq this-command #'corfu-insert-separator) + ;; with separator, any further chars allowed + (seq-contains-p (car corfu--input) corfu-separator))) + (funcall completion-in-region-mode--predicate))))))) + +(defun corfu--preview-current-p () + "Return t if the selected candidate is previewed." + (and corfu-preview-current (>= corfu--index 0) (/= corfu--index corfu--preselect))) + +(defun corfu--preview-current (beg end) + "Show current candidate as overlay given BEG and END." + (when (corfu--preview-current-p) + (setq beg (+ beg (length corfu--base)) + corfu--preview-ov (make-overlay beg end nil)) + (overlay-put corfu--preview-ov 'priority 1000) + (overlay-put corfu--preview-ov 'window (selected-window)) + (overlay-put corfu--preview-ov (if (= beg end) 'after-string 'display) + (nth corfu--index corfu--candidates)))) + +(defun corfu--window-change (_) + "Window and buffer change hook which quits Corfu." + (unless (corfu--range-valid-p) + (corfu-quit))) + +(defun corfu--post-command () + "Refresh Corfu after last command." + (if (corfu--continue-p) + (corfu--exhibit) + (corfu-quit)) + (when corfu-auto + (corfu--auto-post-command))) + +(defun corfu--goto (index) + "Go to candidate with INDEX." + (setq corfu--index (max corfu--preselect (min index (1- corfu--total))))) + +(defun corfu--exit-function (str status cands) + "Call the `:exit-function' with STR and STATUS. +Lookup STR in CANDS to restore text properties." + (when-let ((exit (plist-get completion-extra-properties :exit-function))) + (funcall exit (or (car (member str cands)) str) status))) + +(defun corfu--done (str status cands) + "Exit completion and call the exit function with STR and STATUS. +Lookup STR in CANDS to restore text properties." + (let ((completion-extra-properties (nth 4 completion-in-region--data))) + ;; For successful completions, amalgamate undo operations, + ;; such that completion can be undone in a single step. + (undo-amalgamate-change-group corfu--change-group) + (corfu-quit) + (corfu--exit-function str status cands))) + +(defun corfu--setup (beg end table pred) + "Setup Corfu completion state. +See `completion-in-region' for the arguments BEG, END, TABLE, PRED." + (setq beg (if (markerp beg) beg (copy-marker beg)) + end (if (and (markerp end) (marker-insertion-type end)) end (copy-marker end t)) + completion-in-region--data (list beg end table pred completion-extra-properties)) + (completion-in-region-mode 1) + (activate-change-group (setq corfu--change-group (prepare-change-group))) + (setcdr (assq #'completion-in-region-mode minor-mode-overriding-map-alist) corfu-map) + (add-hook 'pre-command-hook #'corfu--prepare nil 'local) + (add-hook 'window-selection-change-functions #'corfu--window-change nil 'local) + (add-hook 'window-buffer-change-functions #'corfu--window-change nil 'local) + (add-hook 'post-command-hook #'corfu--post-command) + ;; Disable default post-command handling, since we have our own + ;; checks in `corfu--post-command'. + (remove-hook 'post-command-hook #'completion-in-region--postch) + (let ((sym (make-symbol "corfu--teardown")) + (buf (current-buffer))) + (fset sym (lambda () + ;; Ensure that the tear-down runs in the correct buffer, if still alive. + (unless completion-in-region-mode + (remove-hook 'completion-in-region-mode-hook sym) + (corfu--teardown buf)))) + (add-hook 'completion-in-region-mode-hook sym))) + +(defun corfu--in-region (&rest args) + "Corfu completion in region function called with ARGS." + ;; XXX We can get an endless loop when `completion-in-region-function' is set + ;; globally to `corfu--in-region'. This should never happen. + (apply (if (corfu--popup-support-p) #'corfu--in-region-1 + (default-value 'completion-in-region-function)) + args)) + +(defun corfu--in-region-1 (beg end table &optional pred) + "Complete in region, see `completion-in-region' for BEG, END, TABLE, PRED." + (barf-if-buffer-read-only) + ;; Restart the completion. This can happen for example if C-M-/ + ;; (`dabbrev-completion') is pressed while the Corfu popup is already open. + (when completion-in-region-mode (corfu-quit)) + (let* ((pt (max 0 (- (point) beg))) + (str (buffer-substring-no-properties beg end)) + (metadata (completion-metadata (substring str 0 pt) table pred)) + (threshold (completion--cycle-threshold metadata)) + (completion-in-region-mode-predicate + (or completion-in-region-mode-predicate #'always))) + (pcase (completion-try-completion str table pred pt metadata) + ('nil (corfu--message "No match") nil) + ('t (goto-char end) + (corfu--message "Sole match") + (if (eq corfu-on-exact-match 'show) + (corfu--setup beg end table pred) + (corfu--exit-function + str 'finished + (alist-get 'corfu--candidates (corfu--recompute str pt table pred)))) + t) + (`(,newstr . ,newpt) + (setq beg (if (markerp beg) beg (copy-marker beg)) + end (copy-marker end t)) + (corfu--replace beg end newstr) + (goto-char (+ beg newpt)) + (let* ((state (corfu--recompute newstr newpt table pred)) + (base (alist-get 'corfu--base state)) + (total (alist-get 'corfu--total state)) + (candidates (alist-get 'corfu--candidates state))) + (if (= total 1) + ;; If completion is finished and cannot be further completed, and + ;; the value of `corfu-on-exact-match' is not 'show, return + ;; 'finished. Otherwise setup the Corfu popup. + (if (or (eq corfu-on-exact-match 'show) + (consp (completion-try-completion + newstr table pred newpt + (completion-metadata newstr table pred)))) + (corfu--setup beg end table pred) + (corfu--exit-function newstr 'finished candidates)) + (if (or (= total 0) (not threshold) + (and (not (eq threshold t)) (< threshold total))) + (corfu--setup beg end table pred) + (corfu--cycle-candidates total candidates (+ (length base) beg) end) + ;; Do not show Corfu when "trivially" cycling, i.e., + ;; when the completion is finished after the candidate. + (unless (equal (completion-boundaries (car candidates) table pred "") + '(0 . 0)) + (corfu--setup beg end table pred))))) + t)))) + +(defun corfu--message (&rest msg) + "Show completion MSG." + (let (message-log-max) (apply #'message msg))) + +(defun corfu--cycle-candidates (total cands beg end) + "Cycle between TOTAL number of CANDS. +See `completion-in-region' for the arguments BEG, END, TABLE, PRED." + (let* ((idx 0) + (map (make-sparse-keymap)) + (replace (lambda () + (interactive) + (corfu--replace beg end (nth idx cands)) + (corfu--message "Cycling %d/%d..." (1+ idx) total) + (setq idx (mod (1+ idx) total)) + (set-transient-map map)))) + (define-key map [remap completion-at-point] replace) + (define-key map [remap corfu-complete] replace) + (define-key map (vector last-command-event) replace) + (funcall replace))) + +(defun corfu--auto-complete-deferred (&optional tick) + "Initiate auto completion if TICK did not change." + (when (and (not completion-in-region-mode) + (or (not tick) (equal tick (corfu--auto-tick)))) + (pcase (while-no-input ;; Interruptible Capf query + (run-hook-wrapped 'completion-at-point-functions #'corfu--capf-wrapper)) + (`(,fun ,beg ,end ,table . ,plist) + (let ((completion-in-region-mode-predicate + (lambda () + (when-let ((newbeg (car-safe (funcall fun)))) + (= newbeg beg)))) + (completion-extra-properties plist)) + (corfu--setup beg end table (plist-get plist :predicate)) + (corfu--exhibit 'auto)))))) + +(defun corfu--auto-post-command () + "Post command hook which initiates auto completion." + (cancel-timer corfu--auto-timer) + (if (and (not completion-in-region-mode) + (not defining-kbd-macro) + (not buffer-read-only) + (corfu--match-symbol-p corfu-auto-commands this-command) + (corfu--popup-support-p)) + (if (<= corfu-auto-delay 0) + (corfu--auto-complete-deferred) + ;; Do not use `timer-set-idle-time' since this leads to + ;; unpredictable pauses, in particular with `flyspell-mode'. + (timer-set-time corfu--auto-timer + (timer-relative-time nil corfu-auto-delay)) + (timer-set-function corfu--auto-timer #'corfu--auto-complete-deferred + (list (corfu--auto-tick))) + (timer-activate corfu--auto-timer)))) + +(defun corfu--auto-tick () + "Return the current tick/status of the buffer. +Auto completion is only performed if the tick did not change." + (list (selected-window) (current-buffer) (buffer-chars-modified-tick) (point))) + +(cl-defgeneric corfu--popup-show (pos off width lines &optional curr lo bar) + "Show LINES as popup at POS - OFF. +WIDTH is the width of the popup. +The current candidate CURR is highlighted. +A scroll bar is displayed from LO to LO+BAR." + (let ((lh (default-line-height))) + (with-current-buffer (corfu--make-buffer " *corfu*") + (let* ((ch (default-line-height)) + (cw (default-font-width)) + (ml (ceiling (* cw corfu-left-margin-width))) + (mr (ceiling (* cw corfu-right-margin-width))) + (bw (ceiling (min mr (* cw corfu-bar-width)))) + (marginl (and (> ml 0) (propertize " " 'display `(space :width (,ml))))) + (marginr (and (> mr 0) (propertize " " 'display `(space :align-to right)))) + (sbar (when (> bw 0) + (concat (propertize " " 'display `(space :align-to (- right (,mr)))) + (propertize " " 'display `(space :width (,(- mr bw)))) + (propertize " " 'face 'corfu-bar 'display `(space :width (,bw)))))) + (pos (posn-x-y pos)) + (width (+ (* width cw) ml mr)) + ;; XXX HACK: Minimum popup height must be at least 1 line of the + ;; parent frame (gh:minad/corfu#261). + (height (max lh (* (length lines) ch))) + (edge (window-inside-pixel-edges)) + (border (alist-get 'internal-border-width corfu--frame-parameters)) + (x (max 0 (min (+ (car edge) (- (or (car pos) 0) ml (* cw off) border)) + (- (frame-pixel-width) width)))) + (yb (+ (cadr edge) (window-tab-line-height) (or (cdr pos) 0) lh)) + (y (if (> (+ yb (* corfu-count ch) lh lh) (frame-pixel-height)) + (- yb height lh border border) + yb)) + (row 0)) + (with-silent-modifications + (erase-buffer) + (insert (mapconcat (lambda (line) + (let ((str (concat marginl line + (if (and lo (<= lo row (+ lo bar))) + sbar + marginr)))) + (when (eq row curr) + (add-face-text-property + 0 (length str) 'corfu-current 'append str)) + (cl-incf row) + str)) + lines "\n")) + (goto-char (point-min))) + (setq corfu--frame (corfu--make-frame corfu--frame x y + width height (current-buffer))))))) + +(cl-defgeneric corfu--popup-hide () + "Hide Corfu popup." + (corfu--hide-frame corfu--frame)) + +(cl-defgeneric corfu--popup-support-p () + "Return non-nil if child frames are supported." + (display-graphic-p)) + +(cl-defgeneric corfu--insert (status) + "Insert current candidate, exit with STATUS if non-nil." + ;; XXX There is a small bug here, depending on interpretation. + ;; When completing "~/emacs/master/li|/calc" where "|" is the + ;; cursor, then the candidate only includes the prefix + ;; "~/emacs/master/lisp/", but not the suffix "/calc". Default + ;; completion has the same problem when selecting in the + ;; *Completions* buffer. See bug#48356. + (pcase-let* ((`(,beg ,end . ,_) completion-in-region--data) + (str (concat corfu--base (nth corfu--index corfu--candidates)))) + (corfu--replace beg end str) + (corfu--goto -1) ;; Reset selection, completion may continue. + (when status (corfu--done str status nil)) + str)) + +(cl-defgeneric corfu--affixate (cands) + "Annotate CANDS with annotation function." + (let* ((completion-extra-properties (nth 4 completion-in-region--data)) + (dep (plist-get completion-extra-properties :company-deprecated)) + (mf (run-hook-with-args-until-success 'corfu-margin-formatters corfu--metadata))) + (setq cands + (if-let ((aff (or (corfu--metadata-get 'affixation-function) + (plist-get completion-extra-properties :affixation-function)))) + (funcall aff cands) + (if-let ((ann (or (corfu--metadata-get 'annotation-function) + (plist-get completion-extra-properties :annotation-function)))) + (cl-loop for cand in cands collect + (let ((suff (or (funcall ann cand) ""))) + ;; The default completion UI adds the + ;; `completions-annotations' face if no other faces are + ;; present. We use a custom `corfu-annotations' face to + ;; allow further styling which fits better for popups. + (unless (text-property-not-all 0 (length suff) 'face nil suff) + (setq suff (propertize suff 'face 'corfu-annotations))) + (list cand "" suff))) + (cl-loop for cand in cands collect (list cand "" ""))))) + (cl-loop for x in cands for (c . _) = x do + (when mf + (setf (cadr x) (funcall mf c))) + (when (and dep (funcall dep c)) + (setcar x (setq c (substring c))) + (add-face-text-property 0 (length c) 'corfu-deprecated 'append c))) + (cons mf cands))) + +(cl-defgeneric corfu--prepare () + "Insert selected candidate unless command is marked to continue completion." + (when corfu--preview-ov + (delete-overlay corfu--preview-ov) + (setq corfu--preview-ov nil)) + ;; Ensure that state is initialized before next Corfu command + (when (and (symbolp this-command) (string-prefix-p "corfu-" (symbol-name this-command))) + (corfu--update)) + ;; If the next command is not listed in `corfu-continue-commands', insert the + ;; currently selected candidate and bail out of completion. This way you can + ;; continue typing after selecting a candidate. The candidate will be inserted + ;; and your new input will be appended. + (and (corfu--preview-current-p) (eq corfu-preview-current 'insert) + ;; See the comment about `overriding-local-map' in `corfu--post-command'. + (not (or overriding-terminal-local-map + (corfu--match-symbol-p corfu-continue-commands this-command))) + (corfu--insert 'exact))) + +(cl-defgeneric corfu--exhibit (&optional auto) + "Exhibit Corfu UI. +AUTO is non-nil when initializing auto completion." + (pcase-let ((`(,beg ,end ,table ,pred . ,_) completion-in-region--data) + (`(,str . ,pt) (corfu--update 'interruptible))) + (cond + ;; 1) Single exactly matching candidate and no further completion is possible. + ((and (not (equal str "")) + (equal (car corfu--candidates) str) (not (cdr corfu--candidates)) + (not (eq corfu-on-exact-match 'show)) + (or auto corfu-on-exact-match) + (not (consp (completion-try-completion str table pred pt corfu--metadata)))) + ;; Quit directly when initializing auto completion. + (if (or auto (eq corfu-on-exact-match 'quit)) + (corfu-quit) + (corfu--done (car corfu--candidates) 'finished nil))) + ;; 2) There exist candidates => Show candidates popup. + (corfu--candidates + (let ((pos (posn-at-point (+ beg (length corfu--base))))) + (corfu--preview-current beg end) + (corfu--candidates-popup pos))) + ;; 3) No candidates & `corfu-quit-no-match' & initialized => Confirmation popup. + ((pcase-exhaustive corfu-quit-no-match + ('t nil) + ('nil corfu--input) + ('separator (seq-contains-p (car corfu--input) corfu-separator))) + (corfu--popup-show (posn-at-point beg) 0 8 '(#("No match" 0 8 (face italic))))) + ;; 4) No candidates & auto completing or initialized => Quit. + ((or auto corfu--input) (corfu-quit))))) + +(cl-defgeneric corfu--teardown (buffer) + "Tear-down Corfu in BUFFER, which might be dead at this point." + (corfu--popup-hide) + (when corfu--preview-ov (delete-overlay corfu--preview-ov)) + (remove-hook 'post-command-hook #'corfu--post-command) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (remove-hook 'window-selection-change-functions #'corfu--window-change 'local) + (remove-hook 'window-buffer-change-functions #'corfu--window-change 'local) + (remove-hook 'pre-command-hook #'corfu--prepare 'local) + (accept-change-group corfu--change-group))) + (cl-loop for (k . v) in corfu--initial-state do (set k v))) + +(defun corfu-sort-length-alpha (list) + "Sort LIST by length and alphabetically." + (sort list #'corfu--length-string<)) + +(defun corfu-quit () + "Quit Corfu completion." + (interactive) + (completion-in-region-mode -1)) + +(defun corfu-reset () + "Reset Corfu completion. +This command can be executed multiple times by hammering the ESC key. If a +candidate is selected, unselect the candidate. Otherwise reset the input. If +there hasn't been any input, then quit." + (interactive) + (if (/= corfu--index corfu--preselect) + (progn + (corfu--goto -1) + (setq this-command #'corfu-first)) + ;; Cancel all changes and start new change group. + (pcase-let* ((`(,beg ,end . ,_) completion-in-region--data) + (str (buffer-substring-no-properties beg end))) + (cancel-change-group corfu--change-group) + (activate-change-group (setq corfu--change-group (prepare-change-group))) + ;; Quit when resetting, when input did not change. + (when (equal str (buffer-substring-no-properties beg end)) + (corfu-quit))))) + +(defun corfu-insert-separator () + "Insert a separator character, inhibiting quit on completion boundary. +See `corfu-separator' for more details." + (interactive) + (insert corfu-separator)) + +(defun corfu-next (&optional n) + "Go forward N candidates." + (interactive "p") + (let ((index (+ corfu--index (or n 1)))) + (corfu--goto + (cond + ((not corfu-cycle) index) + ((= corfu--total 0) -1) + ((< corfu--preselect 0) (1- (mod (1+ index) (1+ corfu--total)))) + (t (mod index corfu--total)))))) + +(defun corfu-previous (&optional n) + "Go backward N candidates." + (interactive "p") + (corfu-next (- (or n 1)))) + +(defun corfu-scroll-down (&optional n) + "Go back by N pages." + (interactive "p") + (corfu--goto (max 0 (- corfu--index (* (or n 1) corfu-count))))) + +(defun corfu-scroll-up (&optional n) + "Go forward by N pages." + (interactive "p") + (corfu-scroll-down (- (or n 1)))) + +(defun corfu-first () + "Go to first candidate. +If the first candidate is already selected, go to the prompt." + (interactive) + (corfu--goto (if (> corfu--index 0) 0 -1))) + +(defun corfu-last () + "Go to last candidate." + (interactive) + (corfu--goto (1- corfu--total))) + +(defun corfu-prompt-beginning (arg) + "Move to beginning of the prompt line. +If the point is already the beginning of the prompt move to the +beginning of the line. If ARG is not 1 or nil, move backward ARG - 1 +lines first." + (interactive "^p") + (let ((beg (car completion-in-region--data))) + (if (or (not (eq arg 1)) + (and (= corfu--preselect corfu--index) (= (point) beg))) + (move-beginning-of-line arg) + (corfu--goto -1) + (goto-char beg)))) + +(defun corfu-prompt-end (arg) + "Move to end of the prompt line. +If the point is already the end of the prompt move to the end of +the line. If ARG is not 1 or nil, move forward ARG - 1 lines +first." + (interactive "^p") + (let ((end (cadr completion-in-region--data))) + (if (or (not (eq arg 1)) + (and (= corfu--preselect corfu--index) (= (point) end))) + (move-end-of-line arg) + (corfu--goto -1) + (goto-char end)))) + +(defun corfu-complete () + "Complete current input. +If a candidate is selected, insert it. Otherwise invoke +`corfu-expand'. Return non-nil if the input has been expanded." + (interactive) + (if (< corfu--index 0) + (corfu-expand) + ;; Continue completion with selected candidate. Exit with status 'finished + ;; if input is a valid match and no further completion is + ;; possible. Additionally treat completion as finished if at the end of a + ;; boundary, even if other longer candidates would still match, since the + ;; user invoked `corfu-complete' with an explicitly selected candidate! + (pcase-let ((`(,_beg ,_end ,table ,pred . ,_) completion-in-region--data) + (newstr (corfu--insert nil))) + (and (test-completion newstr table pred) + (or (not (consp (completion-try-completion + newstr table pred (length newstr) + (completion-metadata newstr table pred)))) + (equal (completion-boundaries newstr table pred "") '(0 . 0))) + (corfu--done newstr 'finished nil)) + t))) + +(defun corfu-expand () + "Expands the common prefix of all candidates. +If the currently selected candidate is previewed, invoke +`corfu-complete' instead. Expansion relies on the completion +styles via `completion-try-completion'. Return non-nil if the +input has been expanded." + (interactive) + (if (corfu--preview-current-p) + (corfu-complete) + (pcase-let* ((`(,beg ,end ,table ,pred . ,_) completion-in-region--data) + (pt (max 0 (- (point) beg))) + (str (buffer-substring-no-properties beg end)) + (metadata (completion-metadata (substring str 0 pt) table pred))) + (pcase (completion-try-completion str table pred pt metadata) + ('t + (goto-char end) + (corfu--done str 'finished corfu--candidates) + t) + ((and `(,newstr . ,newpt) (guard (not (and (= pt newpt) (equal newstr str))))) + (corfu--replace beg end newstr) + (goto-char (+ beg newpt)) + ;; Exit with status 'finished if input is a valid match + ;; and no further completion is possible. + (and (test-completion newstr table pred) + (not (consp (completion-try-completion + newstr table pred newpt + (completion-metadata (substring newstr 0 newpt) table pred)))) + (corfu--done newstr 'finished corfu--candidates)) + t))))) + +(defun corfu-insert () + "Insert current candidate. +Quit if no candidate is selected." + (interactive) + (if (>= corfu--index 0) + (corfu--insert 'finished) + (corfu-quit))) + +;;;###autoload +(define-minor-mode corfu-mode + "COmpletion in Region FUnction." + :group 'corfu :keymap corfu-mode-map + (cond + (corfu-mode + (and corfu-auto (add-hook 'post-command-hook #'corfu--auto-post-command nil 'local)) + (setq-local completion-in-region-function #'corfu--in-region)) + (t + (remove-hook 'post-command-hook #'corfu--auto-post-command 'local) + (kill-local-variable 'completion-in-region-function)))) + +(defcustom global-corfu-modes t + "List of modes where Corfu should be enabled. +The variable can either be t, nil or a list of t, nil, mode +symbols or elements of the form (not modes). Examples: + - Enable everywhere, except in Org: ((not org-mode) t). + - Enable in programming modes except Python: ((not python-mode) prog-mode). + - Enable only in text modes: (text-mode)." + :type '(choice (const t) (repeat sexp))) + +;;;###autoload +(define-globalized-minor-mode global-corfu-mode + corfu-mode corfu--on + :group 'corfu) + +(defun corfu--on () + "Turn `corfu-mode' on." + (when (and (not (or noninteractive (eq (aref (buffer-name) 0) ?\s))) + ;; TODO backport `easy-mmode--globalized-predicate-p' + (or (eq t global-corfu-modes) + (eq t (cl-loop for p in global-corfu-modes thereis + (pcase-exhaustive p + ('t t) + ('nil 0) + ((pred symbolp) (and (derived-mode-p p) t)) + (`(not . ,m) (and (seq-some #'derived-mode-p m) 0))))))) + (corfu-mode 1))) + +;; Emacs 28: Do not show Corfu commands with M-X +(dolist (sym '(corfu-next corfu-previous corfu-first corfu-last corfu-quit corfu-reset + corfu-complete corfu-insert corfu-scroll-up corfu-scroll-down + corfu-insert-separator corfu-prompt-beginning corfu-prompt-end)) + (put sym 'completion-predicate #'ignore)) + +(defun corfu--capf-wrapper-advice (orig fun which) + "Around advice for `completion--capf-wrapper'. +The ORIG function takes the FUN and WHICH arguments." + (if corfu-mode (corfu--capf-wrapper fun t) (funcall orig fun which))) + +(defun corfu--eldoc-advice () + "Return non-nil if Corfu is currently not active." + (not (and corfu-mode completion-in-region-mode))) + +;; Install advice which fixes `completion--capf-wrapper', such that it respects +;; the completion styles for non-exclusive Capfs. See also the fixme comment in +;; the `completion--capf-wrapper' function in minibuffer.el. +(advice-add #'completion--capf-wrapper :around #'corfu--capf-wrapper-advice) + +;; Register Corfu with ElDoc +(advice-add #'eldoc-display-message-no-interference-p + :before-while #'corfu--eldoc-advice) +(eldoc-add-command #'corfu-complete #'corfu-insert) + +(provide 'corfu) +;;; corfu.el ends here diff --git a/elpa/corfu-1.3/corfu.info b/elpa/corfu-1.3/corfu.info @@ -0,0 +1,795 @@ +This is docxDqOT0.info, produced by makeinfo version 6.8 from +corfu.texi. + +INFO-DIR-SECTION Emacs misc features +START-INFO-DIR-ENTRY +* Corfu: (corfu). COmpletion in Region FUnction. +END-INFO-DIR-ENTRY + + +File: docxDqOT0.info, Node: Top, Next: Features, Up: (dir) + +corfu.el - COmpletion in Region FUnction +**************************************** + +Corfu enhances in-buffer completion with a small completion popup. The +current candidates are shown in a popup below or above the point. The +candidates can be selected by moving up and down. Corfu is the +minimalistic in-buffer completion counterpart of the Vertico +(https://github.com/minad/vertico) minibuffer UI. + + Corfu is a small package, which relies on the Emacs completion +facilities and concentrates on providing a polished completion UI. +In-buffer completion UIs in Emacs can hook into ‘completion-in-region’, +which implements the interaction with the user. Completions at point +are either provided by commands like ‘dabbrev-completion’ or by +pluggable backends (‘completion-at-point-functions’, Capfs) and are then +passed to ‘completion-in-region’. Many programming, text and shell +major modes implement a Capf. Corfu does not include its own completion +backends. The Emacs built-in Capfs and the Capfs provided by +third-party programming language packages are often sufficient. +Additional Capfs and completion utilities are provided by the Cape +(https://github.com/minad/cape) package. + + *NOTE*: Corfu uses child frames to show the popup and falls back to +the default setting of the ‘completion-in-region-function’ on +non-graphical displays. If you want to use Corfu in the terminal, +install the package corfu-terminal +(https://codeberg.org/akib/emacs-corfu-terminal), which provides an +alternative overlay-based display. + +* Menu: + +* Features:: +* Installation:: +* Key bindings:: +* Configuration:: +* Extensions:: +* Complementary packages:: +* Alternatives:: +* Debugging Corfu:: +* Contributions:: + +— The Detailed Node Listing — + +Configuration + +* Auto completion:: +* Completing in the minibuffer:: +* Completing in the Eshell or Shell:: +* Orderless completion:: +* TAB-only completion:: +* TAB-and-Go completion:: +* Expanding to the common candidate prefix with TAB:: +* Transfer completion to the minibuffer:: + + + +File: docxDqOT0.info, Node: Features, Next: Installation, Prev: Top, Up: Top + +1 Features +********** + + • Timer-based auto-completions (_off_ by default, set ‘corfu-auto’). + • Popup display with scrollbar indicator and arrow key navigation. + • The popup can be summoned explicitly by pressing ‘TAB’ at any time. + • The current candidate is inserted with ‘TAB’ and selected with + ‘RET’. + • Candidate sorting by prefix, string length and alphabetically. + • The selected candidate is previewed (configurable via + ‘corfu-preview-current’). + • The selected candidate is automatically committed on further input + by default. (configurable via ‘corfu-preview-current’). + • Supports the Orderless (https://github.com/oantolin/orderless) + completion style. The filter string can contain arbitrary + characters, after inserting a space via ‘M-SPC’ (configurable via + ‘corfu-quit-at-boundary’ and ‘corfu-separator’). + • Lazy completion candidate highlighting for performance. + • Support for candidate annotations (‘annotation-function’, + ‘affixation-function’). + • Deprecated candidates are displayed as crossed out. + • Icons can be provided by an external package via margin formatter + functions. + • Rich set of extensions: Quick keys, Index keys, Sorting by history, + Candidate documentation in echo area, popup or separate buffer. + + +File: docxDqOT0.info, Node: Installation, Next: Key bindings, Prev: Features, Up: Top + +2 Installation +************** + +Corfu is available from GNU ELPA +(https://elpa.gnu.org/packages/corfu.html). You can install it directly +via ‘M-x package-install RET corfu RET’. After installation, activate +the global minor mode with ‘M-x global-corfu-mode RET’. Set the +variable ‘corfu-auto’ to t in order to enable auto completion. For +manual completion press ‘M-TAB’ (or ‘TAB’) within a buffer. + + +File: docxDqOT0.info, Node: Key bindings, Next: Configuration, Prev: Installation, Up: Top + +3 Key bindings +************** + +Corfu uses a transient keymap ‘corfu-map’ which is active while the +popup is shown. The keymap defines the following remappings of +fundamental commands and bindings: + +Binding/Remapping Corfu command +------------------------------------------------------------ +‘move-beginning-of-line’ ‘corfu-prompt-beginning’ +‘move-end-of-line’ ‘corfu-prompt-end’ +‘beginning-of-buffer’ ‘corfu-first’ +‘end-of-buffer’ ‘corfu-last’ +‘scroll-down-command’ ‘corfu-scroll-down’ +‘scroll-up-command’ ‘corfu-scroll-up’ +‘next-line’, ‘down’, ‘M-n’ ‘corfu-next’ +‘previous-line’, ‘up’, ‘M-p’ ‘corfu-previous’ +‘completion-at-point’, ‘TAB’ ‘corfu-complete’ +‘M-TAB’ ‘corfu-expand’ +‘RET’ ‘corfu-insert’ +‘M-g’ ‘corfu-info-location’ +‘M-h’ ‘corfu-info-documentation’ +‘M-SPC’ ‘corfu-insert-separator’ +‘C-g’ ‘corfu-quit’ +‘keyboard-escape-quit’ ‘corfu-reset’ + + +File: docxDqOT0.info, Node: Configuration, Next: Extensions, Prev: Key bindings, Up: Top + +4 Configuration +*************** + +In order to configure Corfu and other packages in your init.el, you may +want to use ‘use-package’. Corfu is flexibly customizable via ‘corfu-*’ +customization variables, such that you can adapt it precisely to your +requirements. However in order to quickly try out the Corfu completion +package, it should be sufficient to activate ‘global-corfu-mode’. You +can experiment with manual completion for example in an Elisp buffer or +in an Eshell or Shell buffer. For auto completion, set ‘corfu-auto’ to +t before turning on ‘global-corfu-mode’. + + Here is an example configuration: + + (use-package corfu + ;; Optional customizations + ;; :custom + ;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' + ;; (corfu-auto t) ;; Enable auto completion + ;; (corfu-separator ?\s) ;; Orderless field separator + ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary + ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match + ;; (corfu-preview-current nil) ;; Disable current candidate preview + ;; (corfu-preselect 'prompt) ;; Preselect the prompt + ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches + ;; (corfu-scroll-margin 5) ;; Use scroll margin + + ;; Enable Corfu only for certain modes. + ;; :hook ((prog-mode . corfu-mode) + ;; (shell-mode . corfu-mode) + ;; (eshell-mode . corfu-mode)) + + ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can + ;; be used globally (M-/). See also the customization variable + ;; `global-corfu-modes' to exclude certain modes. + :init + (global-corfu-mode)) + + ;; A few more useful configurations... + (use-package emacs + :init + ;; TAB cycle if there are only few candidates + ;; (setq completion-cycle-threshold 3) + + ;; Enable indentation+completion using the TAB key. + ;; `completion-at-point' is often bound to M-TAB. + (setq tab-always-indent 'complete) + + ;; Emacs 30 and newer: Disable Ispell completion function. As an alternative, + ;; try `cape-dict'. + (setq text-mode-ispell-word-completion nil) + + ;; Emacs 28 and newer: Hide commands in M-x which do not apply to the current + ;; mode. Corfu commands are hidden, since they are not used via M-x. This + ;; setting is useful beyond Corfu. + (setq read-extended-command-predicate #'command-completion-default-include-p)) + + Dabbrev completion is based on ‘completion-in-region’ and can be used +with Corfu. You may want to swap the ‘dabbrev-completion’ with the +‘dabbrev-expand’ key for easier access, if you prefer completion. Also +take a look at the ‘cape-dabbrev’ completion at point function provided +by my Cape (https://github.com/minad/cape) package. + + ;; Use Dabbrev with Corfu! + (use-package dabbrev + ;; Swap M-/ and C-M-/ + :bind (("M-/" . dabbrev-completion) + ("C-M-/" . dabbrev-expand)) + :config + (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ") + ;; Since 29.1, use `dabbrev-ignored-buffer-regexps' on older. + (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode) + (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode)) + + If you start to configure the package more deeply, I recommend to +give the Orderless completion style a try for filtering. Orderless +completion is different from the familiar prefix TAB completion. Corfu +can be used with the default completion styles. The use of Orderless is +not a necessity. + + ;; Optionally use the `orderless' completion style. + (use-package orderless + :init + ;; Configure a custom style dispatcher (see the Consult wiki) + ;; (setq orderless-style-dispatchers '(+orderless-dispatch) + ;; orderless-component-separator #'orderless-escapable-split-on-space) + (setq completion-styles '(orderless basic) + completion-category-defaults nil + completion-category-overrides '((file (styles partial-completion))))) + + The ‘basic’ completion style is specified as fallback in addition to +‘orderless’ in order to ensure that completion commands which rely on +dynamic completion tables, e.g., ‘completion-table-dynamic’ or +‘completion-table-in-turn’, work correctly. See ‘+orderless-dispatch’ +in the Consult wiki (https://github.com/minad/consult/wiki) for an +advanced Orderless style dispatcher. Additionally enable +‘partial-completion’ for file path expansion. ‘partial-completion’ is +important for file wildcard support. Multiple files can be opened at +once with ‘find-file’ if you enter a wildcard. You may also give the +‘initials’ completion style a try. + + See also the Corfu Wiki (https://github.com/minad/corfu/wiki) and the +Cape manual (https://github.com/minad/cape) for additional Capf +configuration tips. For more general documentation read the chapter +about completion in the Emacs manual +(https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion.html). +If you want to create your own Capfs, you can find documentation about +completion in the Elisp manual +(https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion.html). + +* Menu: + +* Auto completion:: +* Completing in the minibuffer:: +* Completing in the Eshell or Shell:: +* Orderless completion:: +* TAB-only completion:: +* TAB-and-Go completion:: +* Expanding to the common candidate prefix with TAB:: +* Transfer completion to the minibuffer:: + + +File: docxDqOT0.info, Node: Auto completion, Next: Completing in the minibuffer, Up: Configuration + +4.1 Auto completion +=================== + +Auto completion is disabled by default, but can be enabled by setting +‘corfu-auto’ to t. Furthermore you may want to configure Corfu to quit +completion eagerly, such that the completion popup stays out of your way +when it appeared unexpectedly. + + ;; Enable auto completion and configure quitting + (setq corfu-auto t + corfu-quit-no-match 'separator) ;; or t + + I suggest to experiment with the various settings and key bindings to +find a configuration which works for you. There is no one perfect +configuration which fits all. Some people like auto completion, some +like manual completion, some want to cycle with TAB and some with the +arrow keys. + + In case you like auto completion settings, where the completion popup +appears immediately, better use a cheap completion style like ‘basic’, +which performs prefix filtering. In this case Corfu completion should +still be fast in buffers with efficient completion backends. You can +try the following settings in an Elisp buffer or the Emacs scratch +buffer. Note that such settings can slow down Emacs due to the high +load on the Lisp runtime and garbage collector. + + (setq-local corfu-auto t + corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED + corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED + completion-styles '(basic)) + + If you want to combine fast prefix filtering and Orderless filtering +you can still do that by defining a custom Orderless completion style +via ‘orderless-define-completion-style’. We use a custom style +dispatcher, which enables efficient prefix filtering for input shorter +than 4 characters. Note that such a setup is advanced. Please refer to +the Orderless documentation and source code for further details. + + (defun orderless-fast-dispatch (word index total) + (and (= index 0) (= total 1) (length< word 4) + (cons 'orderless-literal-prefix word)))) + + (orderless-define-completion-style orderless-fast + (orderless-style-dispatchers '(orderless-fast-dispatch)) + (orderless-matching-styles '(orderless-literal orderless-regexp))) + + (setq-local corfu-auto t + corfu-auto-delay 0 ;; TOO SMALL - NOT RECOMMENDED + corfu-auto-prefix 1 ;; TOO SMALL - NOT RECOMMENDED + completion-styles '(orderless-fast basic)) + + +File: docxDqOT0.info, Node: Completing in the minibuffer, Next: Completing in the Eshell or Shell, Prev: Auto completion, Up: Configuration + +4.2 Completing in the minibuffer +================================ + +Corfu can be used for completion in the minibuffer, since it relies on +child frames to display the candidates. The Corfu popup can be shown +even if it doesn’t fully fit inside the minibuffer. + + By default, ‘global-corfu-mode’ does not activate ‘corfu-mode’ in the +minibuffer, to avoid interference with specialised minibuffer completion +UIs like Vertico or Mct. However you may still want to enable Corfu +completion for commands like ‘M-:’ (‘eval-expression’) or ‘M-!’ +(‘shell-command’), which read from the minibuffer. In order to detect +minibuffers with completion we check if the variable +‘completion-at-point-functions’ is set locally. + + (defun corfu-enable-in-minibuffer () + "Enable Corfu in the minibuffer." + (when (local-variable-p 'completion-at-point-functions) + ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion + (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) + + This is not recommended, but one can also enable Corfu more generally +for every minibuffer, as long as no completion UI is active. In the +following example we check for Mct and Vertico. Furthermore we ensure +that Corfu is not enabled if a password is read from the minibuffer. + + (defun corfu-enable-always-in-minibuffer () + "Enable Corfu in the minibuffer if Vertico/Mct are not active." + (unless (or (bound-and-true-p mct--active) + (bound-and-true-p vertico--input) + (eq (current-local-map) read-passwd-map)) + ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion + (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-always-in-minibuffer 1) + + +File: docxDqOT0.info, Node: Completing in the Eshell or Shell, Next: Orderless completion, Prev: Completing in the minibuffer, Up: Configuration + +4.3 Completing in the Eshell or Shell +===================================== + +When completing in the Eshell I recommend conservative local settings +without auto completion, such that the completion behavior is similar to +widely used shells like Bash, Zsh or Fish. + + (add-hook 'eshell-mode-hook + (lambda () + (setq-local corfu-auto nil) + (corfu-mode))) + + When pressing ‘RET’ while the Corfu popup is visible, the +‘corfu-insert’ command will be invoked. This command does inserts the +currently selected candidate, but it does not send the prompt input to +Eshell or the Comint process. Therefore you often have to press ‘RET’ +twice which feels like an unnecessary double confirmation. Fortunately +it is easy to improve this! In my configuration I define the advice +‘corfu-send-shell’ which sends the candidate after insertion. + + (defun corfu-send-shell (&rest _) + "Send completion candidate when inside comint/eshell." + (cond + ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) + (eshell-send-input)) + ((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) + (comint-send-input)))) + + (advice-add #'corfu-insert :after #'corfu-send-shell) + + Shell completion uses the flexible Pcomplete mechanism internally, +which allows you to program the completions per shell command. If you +want to know more, look into this blog post +(https://www.masteringemacs.org/article/pcomplete-context-sensitive-completion-emacs), +which shows how to configure Pcomplete for git commands. Since Emacs +29, Pcomplete offers the ‘pcomplete-from-help’ function which parses the +‘--help’ output of a command and produces completions for command line +options. + + Pcomplete has a few bugs on Emacs 28 and older. We can work around +the issues with the Cape (https://github.com/minad/cape) library +(Completion at point extensions). Cape provides wrappers which sanitize +the Pcomplete function. If you use Emacs 28 or older installing these +advices is recommended such that Pcomplete works properly. On Emacs 29 +the advices should not be necessary anymore, since most relevant bugs +have been fixed. I therefore recommend to avoid the advices on Emacs 29 +and eventually report any remaining Pcomplete issues upstream. + + ;; The advices are only needed on Emacs 28 and older. + (when (< emacs-major-version 29) + ;; Silence the pcomplete capf. Hide errors or messages. + (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent) + + ;; Ensure that pcomplete does not write to the buffer and behaves as a + ;; `completion-at-point-function' without side-effects. + (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)) + + +File: docxDqOT0.info, Node: Orderless completion, Next: TAB-only completion, Prev: Completing in the Eshell or Shell, Up: Configuration + +4.4 Orderless completion +======================== + +Orderless (https://github.com/oantolin/orderless) is an advanced +completion style that supports multi-component search filters separated +by a configurable character (space, by default). Normally, entering +characters like space which lie outside the completion region boundaries +(words, typically) causes Corfu to quit. This behavior is helpful with +auto-completion, which may pop-up when not desired, e.g. on entering a +new variable name. Just keep typing and Corfu will get out of the way. + + But orderless search terms can contain arbitrary characters; they are +also interpreted as regular expressions. To use orderless, set +‘corfu-separator’ (a space, by default) to the primary character of your +orderless component separator. + + Then, when a new orderless component is desired, use ‘M-SPC’ +(‘corfu-insert-separator’) to enter the first component separator in the +input, and arbitrary orderless search terms and new separators can be +entered thereafter. + + To treat the entire input as Orderless input, you can set the +customization option ‘corfu-quit-at-boundary’ to nil. This disables the +predicate which checks if the current completion boundary has been left. +In contrast, if you always want to quit at the boundary, set +‘corfu-quit-at-boundary’ to t. By default ‘corfu-quit-at-boundary’ is +set to ‘separator’ which quits at completion boundaries as long as no +separator has been inserted with ‘corfu-insert-separator’. + + Finally, there exists the user option ‘corfu-quit-no-match’ which is +set to ‘separator’ by default. With this setting Corfu stays alive as +soon as you start advanced filtering with a ‘corfu-separator’ even if +there are no matches, for example due to a typo. As long as no +separator character has been inserted with ‘corfu-insert-separator’, +Corfu will still quit if there are no matches. This ensures that the +Corfu popup goes away quickly if completion is not possible. + + In the following we show two configurations, one which works best +with auto completion and one which may work better with manual +completion if you prefer to always use ‘SPC’ to separate the Orderless +components. + + ;; Auto completion example + (use-package corfu + :custom + (corfu-auto t) ;; Enable auto completion + ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space + :bind + ;; Another key binding can be used, such as S-SPC. + ;; (:map corfu-map ("M-SPC" . corfu-insert-separator)) + :init + (global-corfu-mode)) + + ;; Manual completion example + (use-package corfu + :custom + ;; (corfu-separator ?_) ;; Set to orderless separator, if not using space + :bind + ;; Configure SPC for separator insertion + (:map corfu-map ("SPC" . corfu-insert-separator)) + :init + (global-corfu-mode)) + + +File: docxDqOT0.info, Node: TAB-only completion, Next: TAB-and-Go completion, Prev: Orderless completion, Up: Configuration + +4.5 TAB-only completion +======================= + +By default, Corfu steals both the ‘RET’ and ‘TAB’ keys, when the Corfu +popup is open. This can feel intrusive, in particular in combination +with auto completion. ‘RET’ may accidentally commit an automatically +selected candidate, while you actually wanted to start a new line. As +an alternative we can unbind the ‘RET’ key completely from ‘corfu-map’ +or reserve the ‘RET’ key only in shell modes. + + ;; TAB-only configuration + (use-package corfu + :custom + (corfu-auto t) ;; Enable auto completion + (corfu-preselect 'directory) ;; Select the first candidate, except for directories + + ;; Free the RET key for less intrusive behavior. + :bind + (:map corfu-map + ;; Option 1: Unbind RET completely + ;;; ("RET" . nil) + ;; Option 2: Use RET only in shell modes + ("RET" . (menu-item "" nil :filter corfu-insert-shell-filter))) + + :init + (global-corfu-mode)) + + (defun corfu-insert-shell-filter (&optional _) + "Insert completion candidate and send when inside comint/eshell." + (when (or (derived-mode-p 'eshell-mode) (derived-mode-p 'comint-mode)) + (lambda () + (interactive) + (corfu-insert) + ;; `corfu-send-shell' was defined above + (corfu-send-shell)))) + + +File: docxDqOT0.info, Node: TAB-and-Go completion, Next: Expanding to the common candidate prefix with TAB, Prev: TAB-only completion, Up: Configuration + +4.6 TAB-and-Go completion +========================= + +You may be interested in configuring Corfu in TAB-and-Go style. +Pressing TAB moves to the next candidate and further input will then +commit the selection. Note that further input will not expand snippets +or templates, which may not be desired but which leads overall to a more +predictable behavior. In order to force snippet expansion, confirm a +candidate explicitly with ‘RET’. + + (use-package corfu + ;; TAB-and-Go customizations + :custom + (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' + (corfu-preselect 'prompt) ;; Always preselect the prompt + + ;; Use TAB for cycling, default is `corfu-complete'. + :bind + (:map corfu-map + ("TAB" . corfu-next) + ([tab] . corfu-next) + ("S-TAB" . corfu-previous) + ([backtab] . corfu-previous)) + + :init + (global-corfu-mode)) + + +File: docxDqOT0.info, Node: Expanding to the common candidate prefix with TAB, Next: Transfer completion to the minibuffer, Prev: TAB-and-Go completion, Up: Configuration + +4.7 Expanding to the common candidate prefix with TAB +===================================================== + +If you leave the default configuration of the completion styles, such +that the ‘basic’ completion style is still present, then pressing +‘M-TAB’ (‘corfu-expand’) will expand the current input to the common +prefix of all completion candidates. In contrast, ‘TAB’ +(‘corfu-complete’) behaves differently and expands input to the +currently selected candidate. + + If you use the ‘orderless’ completion style, then expansion works +differently by default. Orderless only expands to single matching +candidates, since due to its multi-component input, there does not +necessarily exist an expansion to a common candidate prefix. However it +is possible to define a separate ‘tab’ completion style. The ‘tab’ +completion style will only take over ‘TAB’ completion (if prefix +expansion is possible), but besides that won’t affect Orderless +candidate filtering. + + (add-to-list 'completion-styles-alist + '(tab completion-basic-try-completion ignore + "Completion style which provides TAB completion only.")) + (setq completion-styles '(tab orderless basic))) + + +File: docxDqOT0.info, Node: Transfer completion to the minibuffer, Prev: Expanding to the common candidate prefix with TAB, Up: Configuration + +4.8 Transfer completion to the minibuffer +========================================= + +Sometimes it is useful to transfer the Corfu completion session to the +minibuffer, since the minibuffer offers richer interaction features. In +particular, Embark (https://github.com/oantolin/embark) is available in +the minibuffer, such that you can act on the candidates or +export/collect the candidates to a separate buffer. We could add Corfu +support to Embark in the future, such that export or collect is possible +directly from Corfu. Nevertheless, the ability to transfer the Corfu +completion to the minibuffer is even more powerful, since further +completion is possible. + + The command ‘corfu-move-to-minibuffer’ is defined here in terms of +‘consult-completion-in-region’, which uses the minibuffer completion UI +via ‘completing-read’. + + (defun corfu-move-to-minibuffer () + (interactive) + (pcase completion-in-region--data + (`(,beg ,end ,table ,pred ,extras) + (let ((completion-extra-properties extras) + completion-cycle-threshold completion-cycling) + (consult-completion-in-region beg end table pred))))) + (keymap-set corfu-map "M-m" #'corfu-move-to-minibuffer) + (add-to-list 'corfu-continue-commands #'corfu-move-to-minibuffer) + + +File: docxDqOT0.info, Node: Extensions, Next: Complementary packages, Prev: Configuration, Up: Top + +5 Extensions +************ + +We maintain small extension packages to Corfu in this repository in the +subdirectory extensions/ +(https://github.com/minad/corfu/tree/main/extensions). The extensions +are installed together with Corfu if you pull the package from ELPA. +The extensions are inactive by default and can be enabled manually if +desired. Furthermore it is possible to install all of the files +separately, both ‘corfu.el’ and the ‘corfu-*.el’ extensions. Currently +the following extensions come with the Corfu ELPA package: + + • corfu-echo + (https://github.com/minad/corfu/blob/main/extensions/corfu-echo.el): + ‘corfu-echo-mode’ displays a brief candidate documentation in the + echo area. + • corfu-history + (https://github.com/minad/corfu/blob/main/extensions/corfu-history.el): + ‘corfu-history-mode’ remembers selected candidates and sorts the + candidates by their history position. + • corfu-indexed + (https://github.com/minad/corfu/blob/main/extensions/corfu-indexed.el): + ‘corfu-indexed-mode’ allows you to select indexed candidates with + prefix arguments. + • corfu-info + (https://github.com/minad/corfu/blob/main/extensions/corfu-info.el): + Actions to access the candidate location and documentation. + • corfu-popupinfo + (https://github.com/minad/corfu/blob/main/extensions/corfu-popupinfo.el): + Display candidate documentation or source in a popup next to the + candidate menu. + • corfu-quick + (https://github.com/minad/corfu/blob/main/extensions/corfu-quick.el): + Commands to select using Avy-style quick keys. + + See the Commentary of those files for configuration details. + + +File: docxDqOT0.info, Node: Complementary packages, Next: Alternatives, Prev: Extensions, Up: Top + +6 Complementary packages +************************ + +Corfu works well together with all packages providing code completion +via the ‘completion-at-point-functions’. Many modes and packages +already provide a Capf out of the box. Nevertheless you may want to +look into complementary packages to enhance your setup. + + • corfu-terminal (https://codeberg.org/akib/emacs-corfu-terminal): + The corfu-terminal package provides an overlay-based display for + Corfu, such that you can use Corfu in terminal Emacs. + + • corfu-candidate-overlay + (https://code.bsdgeek.org/adam/corfu-candidate-overlay): Shows + as-you-type auto-suggestion candidate overlay with a visual + indication of whether there are many or exactly one candidate + available (works only with ‘corfu-auto’ disabled). + + • Orderless (https://github.com/oantolin/orderless): Corfu supports + completion styles, including the advanced ‘orderless’ completion + style, where the filter expressions are separated by spaces or + another character (see ‘corfu-separator’). + + • Cape (https://github.com/minad/cape): Provides additional Capf + backends and ‘completion-in-region’ commands. Among others, the + package supplies the file completion backend ‘cape-file’ and the + Dabbrev backend ‘cape-dabbrev’. Cape provides the + ‘cape-company-to-capf’ adapter to reuse Company backends in Corfu. + + • nerd-icons-corfu (https://github.com/LuigiPiucco/nerd-icons-corfu), + kind-icon (https://github.com/jdtsmith/kind-icon): Icons are + supported by Corfu via external packages. The nerd-icons-corfu + package relies on the Nerd icon font, which is even supported on + terminal, while kind-icon uses SVGs from monochromatic icon sets. + + • Tempel (https://github.com/minad/tempel): Tiny template/snippet + package with templates in Lisp syntax, which can be used in + conjunction with Corfu. + + • Vertico (https://github.com/minad/vertico): You may also want to + look into my Vertico package. Vertico is the minibuffer completion + counterpart of Corfu. + + +File: docxDqOT0.info, Node: Alternatives, Next: Debugging Corfu, Prev: Complementary packages, Up: Top + +7 Alternatives +************** + + • Company (https://github.com/company-mode/company-mode): Company is + a widely used and mature completion package, which implements a + similar UI as Corfu. While Corfu relies exclusively on the + standard Emacs completion API (Capfs), Company defines its own API + for the backends. Company includes its own completion backends, + following its own API, which are incompatible with the Emacs + completion infrastructure. Company provides an adapter + ‘company-capf’ to handle Capfs as a Company backend. As a result + of this design, Company is a more complex package than Corfu. + Company by default uses overlays for the popup in contrast to the + child frames used by Corfu. Overall both packages work well, but + Company integrates less tightly with Emacs. The + ‘completion-styles’ support is more limited and the + ‘completion-at-point’ command and the ‘completion-in-region’ + function do not invoke Company. + + • consult-completion-in-region (https://github.com/minad/consult): + The Consult package provides the function + ‘consult-completion-in-region’ which can be set as + ‘completion-in-region-function’ such that it handles + ‘completion-at-point’. The function works by transferring the + in-buffer completion to the minibuffer. In the minibuffer, the + minibuffer completion UI, for example Vertico + (https://github.com/minad/vertico) takes over. If you prefer to + perform all your completions in the minibuffer + ‘consult-completion-in-region’ is your best option. + + +File: docxDqOT0.info, Node: Debugging Corfu, Next: Contributions, Prev: Alternatives, Up: Top + +8 Debugging Corfu +***************** + +When you observe an error in the ‘corfu--post-command’ post command +hook, you should install an advice to enforce debugging. This allows +you to obtain a stack trace in order to narrow down the location of the +error. The reason is that post command hooks are automatically disabled +(and not debugged) by Emacs. Otherwise Emacs would become unusable, +given that the hooks are executed after every command. + + (setq debug-on-error t) + + (defun force-debug (func &rest args) + (condition-case e + (apply func args) + ((debug error) (signal (car e) (cdr e))))) + + (advice-add #'corfu--post-command :around #'force-debug) + + When Capfs do not yield the expected result you can use +‘cape-capf-debug’ to add debug messages to a Capf. The Capf will then +produce a completion log in the messages buffer. + + (setq completion-at-point-functions (list (cape-capf-debug #'cape-dict))) + + +File: docxDqOT0.info, Node: Contributions, Prev: Debugging Corfu, Up: Top + +9 Contributions +*************** + +Since this package is part of GNU ELPA +(https://elpa.gnu.org/packages/corfu.html) contributions require a +copyright assignment to the FSF. + + + +Tag Table: +Node: Top208 +Node: Features2308 +Node: Installation3769 +Node: Key bindings4284 +Node: Configuration5623 +Node: Auto completion11389 +Node: Completing in the minibuffer13912 +Node: Completing in the Eshell or Shell16114 +Node: Orderless completion19072 +Node: TAB-only completion22149 +Node: TAB-and-Go completion23680 +Node: Expanding to the common candidate prefix with TAB24786 +Node: Transfer completion to the minibuffer26201 +Node: Extensions27654 +Node: Complementary packages29455 +Node: Alternatives31685 +Node: Debugging Corfu33431 +Node: Contributions34487 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/corfu-1.0/dir b/elpa/corfu-1.3/dir