aboutsummaryrefslogtreecommitdiff
path: root/.config/emacs/lisp/minadstack/corfu.el
diff options
context:
space:
mode:
authorJack Jamison <jackqjamison@gmail.com>2026-07-30 20:09:00 -0400
committerJack Jamison <jackqjamison@gmail.com>2026-07-30 20:18:37 -0400
commit8c4e09dff83847ac7f07bf1da7751e9328006c4d (patch)
treea0e245567ce225f8bcb63b66e4d2373b5d033e4a /.config/emacs/lisp/minadstack/corfu.el
parent1e33b30749bb1043ffc6ceb5a2fb0977446788b3 (diff)
actual final changes and get rid of junk in lisp dir
actually works fine
Diffstat (limited to '.config/emacs/lisp/minadstack/corfu.el')
-rw-r--r--.config/emacs/lisp/minadstack/corfu.el1444
1 files changed, 0 insertions, 1444 deletions
diff --git a/.config/emacs/lisp/minadstack/corfu.el b/.config/emacs/lisp/minadstack/corfu.el
deleted file mode 100644
index bd3b314..0000000
--- a/.config/emacs/lisp/minadstack/corfu.el
+++ /dev/null
@@ -1,1444 +0,0 @@
-;;; corfu.el --- COmpletion in Region FUnction -*- lexical-binding: t -*-
-
-;; Copyright (C) 2021-2026 Free Software Foundation, Inc.
-
-;; Author: Daniel Mendler <mail@daniel-mendler.de>
-;; Maintainer: Daniel Mendler <mail@daniel-mendler.de>
-;; Created: 2021
-;; Version: 2.10
-;; Package-Requires: ((emacs "29.1") (compat "31"))
-;; URL: 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 "Website" "https://github.com/minad/corfu")
- :link '(url-link :tag "Wiki" "https://github.com/minad/corfu/wiki")
- :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 nil
- "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
- '(ignore universal-argument universal-argument-more digit-argument
- "\\`corfu-" "\\`scroll-other-window")
- "Continue Corfu completion after executing these commands.
-The list can contain 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-border-width 1
- "Width of the border in pixels, only applies to GUI Emacs."
- :type 'natnum)
-
-(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. In order to preserve correct popup
-alignment, the length and display width of the returned string must
-precisely span the same number of characters of the fixed-width popup
-font. For example the kind-icon package returns a string of length 3
-with a display width of 3 characters."
- :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 nil
- "Enable auto completion.
-Auto completion is disabled by default for safety and unobtrusiveness.
-Note that auto completion is particularly dangerous in untrusted files
-since some completion functions may perform arbitrary code execution,
-notably the Emacs built-in `elisp-completion-at-point'. 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")
- (((background dark)) :background "gray" :foreground "black")
- (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" :extend t)
- (((class color) (min-colors 88) (background light))
- :background "#c0efff" :foreground "black" :extend t)
- (t :background "magenta" :foreground "white" :extend t))
- "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 "black"))
- "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
- "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--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.")
-
-(defvar corfu--width 0
- "Popup width of current completion to reduce width fluctuations.")
-
-(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
- corfu--width))
- "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)
- (vertical-scroll-bars . nil)
- (horizontal-scroll-bars . nil)
- (menu-bar-lines . 0)
- (tool-bar-lines . 0)
- (tab-bar-lines . 0)
- (tab-bar-lines-keep-state . t)
- (no-other-frame . t)
- (unsplittable . t)
- (undecorated . t)
- (fullscreen . nil)
- (cursor-type . nil)
- (no-special-glyphs . t)
- (desktop-dont-save . t)
- (inhibit-double-buffering . t)) ;; Avoid display artifacts on X/Gtk builds
- "Default child frame parameters.
-It is recommended to avoid changing these parameters.")
-
-(defvar corfu--buffer-parameters
- '((mode-line-format . nil)
- (header-line-format . nil)
- (tab-line-format . nil)
- (tab-bar-format . nil)
- (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 . 0)
- (right-fringe-width . 0)
- (left-margin-width . 0)
- (right-margin-width . 0)
- (fringes-outside-margins . 0)
- (fringe-indicator-alist (continuation) (truncation))
- (indicate-empty-lines . nil)
- (indicate-buffer-boundaries . nil)
- (buffer-read-only . t)
- (pixel-scroll-precision-mode . nil))
- "Default child frame buffer parameters.
-It is recommended to avoid changing these parameters.")
-
-(defvar corfu--mouse-ignore-map
- (let ((map (define-keymap "<touchscreen-begin>" #'ignore)))
- (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))
- (completion--replace beg end 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, performs sanity checking on the returned result and computes
-the initial completion state. PREFIX is the minimum prefix length."
- (pcase (funcall fun)
- (`(,beg ,end ,table . ,plist)
- (and (integer-or-marker-p beg) ;; Valid Capf result
- (<= beg (point) end) ;; Sanity checking
- ;; Check minimal prefix length if given.
- (or (not prefix)
- (let ((len (or (plist-get plist :company-prefix-length)
- (- (point) beg))))
- (or (eq len t) (>= len prefix))))
- (let* ((str (buffer-substring-no-properties beg end))
- (pt (- (point) beg))
- (pred (plist-get plist :predicate))
- (state (corfu--compute (cons str pt) table pred)))
- (cond ((alist-get 'corfu--candidates state)
- `(,fun ,beg ,end ,table :corfu--state ,state ,@plist))
- ;; Stop with empty result for exclusive Capf.
- ((not (eq 'no (plist-get plist :exclusive)))
- '(nil))))))))
-
-(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-local (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 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)))
-
-;; Not present on non-gtk/non-x builds
-(defvar x-gtk-resize-child-frames)
-(defvar x-fast-protocol-requests)
-
-;; Function adapted from posframe.el by tumashu
-(defun corfu--make-frame (frame x y width height)
- "Show current 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-fast-protocol-requests t)
- (x-gtk-resize-child-frames corfu--gtk-resize-child-frames)
- (before-make-frame-hook)
- (after-make-frame-functions)
- (parent (window-frame))
- (graphic (display-graphic-p parent))
- (params `((background-color
- . ,(face-attribute 'corfu-default :background nil 'default))
- (font . ,(frame-parameter parent 'font))
- (right-fringe . ,right-fringe-width)
- (left-fringe . ,left-fringe-width)
- (internal-border-width . ,corfu-border-width)
- (child-frame-border-width . ,corfu-border-width)
- ,@corfu--frame-parameters)))
- (unless (and (frame-live-p frame)
- (eq (frame-parent frame)
- (and (not (and graphic (bound-and-true-p exwm--connection)))
- parent))
- ;; Handle mixed tty/graphical sessions
- (eq graphic (display-graphic-p frame))
- ;; 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
- `((name . ,(if graphic "EmacsCorfuGUI" "EmacsCorfuTTY"))
- (parent-frame . ,parent)
- (minibuffer . ,(minibuffer-window parent))
- (width . 0) (height . 0) (visibility . nil)
- ,@params))))
- ;; 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 (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* ((win (frame-root-window frame))
- (is (frame-parameters frame))
- (diff (cl-loop for p in params for (k . v) = p
- unless (equal (alist-get k is) v) collect p)))
- (when diff (modify-frame-parameters frame diff))
- ;; XXX HACK: `set-window-buffer' must be called to force fringe update.
- (when (or diff (not (eq (window-buffer win) (current-buffer))))
- (set-window-buffer win (current-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)
- (pcase-let* ((`(,ox ,oy ,right ,bottom) (frame-edges frame 'outer-edges))
- (border (* 2 corfu-border-width))
- (ow (- (- right ox) left-fringe-width right-fringe-width border))
- (oh (- (- bottom oy) border))
- (pos-change (or (/= x ox) (/= y oy)))
- (size-change (or (/= ow width) (/= oh height))))
- (cond
- ((and pos-change size-change)
- ;; TODO: New Emacs 31 function for faster resizing/movement in one go.
- ;; Add this function to Compat 31 as backport.
- (static-if (fboundp 'set-frame-size-and-position-pixelwise)
- (set-frame-size-and-position-pixelwise frame width height x y)
- (set-frame-size frame width height t)
- (set-frame-position frame x y)))
- (pos-change (set-frame-position frame x y))
- (size-change (set-frame-size frame width height t)))))
- (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)
- (display-graphic-p frame) (frame-parent frame))
- (redisplay t)
- (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
- (delete-region (point-min) (point-max))))))
-
-(defun corfu--hide-frame (frame)
- "Hide child FRAME."
- (when (and (frame-live-p frame) (frame-visible-p frame))
- (cond
- ((not (display-graphic-p frame))
- (corfu--hide-frame-deferred 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 all ELEM (also duplicates) to front of LIST."
- (if (member elem list)
- (nconc (cl-loop for x in list if (equal x elem) collect x)
- (delete elem list))
- list))
-
-(defun corfu--filter-completions (&rest args)
- "Compute all completions for ARGS with lazy highlighting."
- (dlet ((completion-lazy-hilit t) (completion-lazy-hilit-fn nil))
- (static-if (>= 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))
- ((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)))))
- (cons (apply #'completion-all-completions args) completion-lazy-hilit-fn)))))
-
-(defun corfu--try-completion (str table pred pt &optional md)
- "Complete STR given TABLE, predicate PRED, point PT and optional metadata MD."
- (setq md (or md (completion-metadata (substring str 0 pt) table pred)))
- (completion-try-completion str table pred pt md))
-
-(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 could
- ;; avoid this via a hash table taking properties into account.
- (while (not (eq beg end))
- (let ((dup beg))
- (while (not (eq (cdr dup) end))
- (if (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--compute (input table pred)
- "Compute state from INPUT, TABLE and PRED."
- (pcase-let* ((`(,str . ,pt) input)
- (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 before 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 (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--delete-dups (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--input . ,input)
- (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))
- (if interruptible
- (while-no-input (corfu--compute input table pred))
- (corfu--compute input table pred)))
- ('nil (keyboard-quit))
- ((and state (pred consp))
- (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."
- ;; Marginalia and various icon packages advise `completion-metadata-get' to
- ;; inject their annotations, but are meant only for minibuffer completion.
- ;; Therefore call `completion-metadata-get' without advices here.
- (let ((completion-extra-properties (nth 4 completion-in-region--data)))
- (funcall (advice--cd*r (symbol-function (compat-function completion-metadata-get)))
- corfu--metadata prop)))
-
-(defun corfu--format-candidates (cands)
- "Format annotated CANDS."
- (cl-loop for c in cands do
- (cl-loop for s in-ref c do
- (setf s (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 (min (max corfu--width corfu-min-width (+ pw cw sw))
- ;; -4 because of margins and some additional safety
- corfu-max-width (- (frame-width) 4)))
- (trunc (not (display-graphic-p))))
- (setq corfu--width width)
- (list pw width
- (cl-loop
- for (cand prefix suffix) in cands collect
- (let ((s (concat
- prefix (make-string (- pw (string-width prefix)) ?\s) cand
- (when (> sw 0)
- (make-string (max 0 (- width pw (string-width cand)
- (string-width suffix)))
- ?\s))
- suffix)))
- (if trunc (truncate-string-to-width s width) s))))))
-
-(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
- ;; bug#77754: Highlight unquoted string.
- (substring (or (get-text-property
- 0 'completion--unquoted c) 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 end)) (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 (equal (or (car 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)
- (corfu--preview-delete)
- (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)
- (substring-no-properties (nth corfu--index corfu--candidates)))))
-
-(defun corfu--preview-delete ()
- "Delete the preview overlay."
- (when corfu--preview-ov
- (delete-overlay corfu--preview-ov)
- (setq corfu--preview-ov nil)))
-
-(defun corfu--window-change (_)
- "Window and buffer change hook which quits Corfu."
- (unless (corfu--range-valid-p)
- (corfu-quit)))
-
-(defun corfu--debug (&rest _)
- "Debugger used by `corfu--protect'."
- (let ((inhibit-message t))
- (require 'backtrace)
- (declare-function backtrace-to-string "backtrace")
- (message "Corfu detected an error:\n%s" (backtrace-to-string)))
- (let (message-log-max)
- (message "%s %s"
- (propertize "Corfu detected an error:" 'face 'error)
- (substitute-command-keys "Press \\[view-echo-area-messages] to see the stack trace")))
- nil)
-
-(defun corfu--protect (fun)
- "Protect FUN such that errors are caught.
-If an error occurs, the FUN is retried with `debug-on-error' enabled and
-the stack trace is shown in the *Messages* buffer."
- (static-if (fboundp 'handler-bind) ;; Available on Emacs 30
- (ignore-errors
- (handler-bind ((error #'corfu--debug))
- (funcall fun)))
- (when (or debug-on-error (condition-case nil
- (progn (funcall fun) nil)
- (error t)))
- (let ((debug-on-error t)
- (debugger #'corfu--debug))
- (condition-case nil
- (funcall fun)
- ((debug error) nil))))))
-
-(defun corfu--post-command ()
- "Refresh Corfu after last command."
- (corfu--protect
- (lambda ()
- (if (corfu--continue-p)
- (corfu--exhibit)
- (corfu-quit)))))
-
-(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."
- (let ((props completion-extra-properties))
- (when (eq (car props) :corfu--state)
- (dolist (s (cadr props)) (set (car s) (cdr s)))
- (setq props (cddr props)))
- (setq end (if (and (markerp end) (marker-insertion-type end)) end (copy-marker end t))
- completion-in-region--data (list (+ 0 beg) end table pred props)))
- (completion-in-region-mode)
- (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 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))
- (input (cons str pt))
- (md (completion-metadata (substring str 0 pt) table pred))
- (threshold (completion--cycle-threshold md))
- (completion-in-region-mode-predicate
- (or completion-in-region-mode-predicate #'always)))
- (pcase (corfu--try-completion str table pred pt md)
- ('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--compute input table pred))))
- t)
- ((and newinp `(,newstr . ,newpt))
- (setq end (copy-marker end t))
- (corfu--replace beg end newstr)
- (goto-char (+ beg newpt))
- (let* ((state (corfu--compute newinp table pred))
- (base (alist-get 'corfu--base state))
- (total (alist-get 'corfu--total state))
- (cands (alist-get 'corfu--candidates state)))
- (cond
- ((= total 0)
- (when (test-completion newstr table pred)
- (corfu--exit-function newstr 'finished nil)))
- ((= total 1)
- ;; Setup popup if `corfu-on-exact-match' is `show' or if completion
- ;; can continue.
- (if (or (eq corfu-on-exact-match 'show)
- (consp (corfu--try-completion newstr table pred newpt)))
- (corfu--setup beg end table pred)
- (corfu--exit-function (car cands) 'finished nil)))
- ;; Too many candidates for cycling -> Setup popup.
- ((or (not threshold) (and (not (eq threshold t)) (< threshold total)))
- (corfu--setup beg end table pred))
- (t
- ;; Cycle through candidates.
- (corfu--cycle-candidates total cands (+ (length base) beg) end)
- ;; Do not show Corfu when completion is finished after the candidate.
- (unless (equal (completion-boundaries (car cands) 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)))
-
-(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 (max (default-line-height) (cdr (posn-object-width-height pos)))))
- (with-current-buffer (corfu--make-buffer " *corfu*")
- (let* ((ch (default-line-height))
- (cw (default-font-width))
- ;; bug#74214, bug#37755, bug#37689: Even for larger fringes, fringe
- ;; bitmaps can only have a width between 1 and 16. Therefore we
- ;; restrict the fringe width to 16 pixel. This restriction may
- ;; cause problem on HDPi systems. Hopefully Emacs will adopt
- ;; larger fringe bitmaps in the future and lift the restriction.
- (ml (min 16 (ceiling (* cw corfu-left-margin-width))))
- (mr (min 16 (ceiling (* cw corfu-right-margin-width))))
- (bw (min mr (ceiling (* cw corfu-bar-width))))
- (graphic (display-graphic-p))
- (marginl (and (not graphic) (propertize " " 'display `(space :width (,ml)))))
- (sbar (if graphic
- #(" " 0 1 (display (right-fringe corfu--bar corfu--bar)))
- (concat
- (propertize " " 'display `(space :align-to (- right (,bw))))
- (propertize " " 'face 'corfu-bar 'display `(space :width (,bw))))))
- (cbar (if graphic
- #(" " 0 1 (display (left-fringe corfu--nil corfu-current))
- 1 2 (display (right-fringe corfu--bar corfu--cbar)))
- sbar))
- (cmargin (and graphic
- #(" " 0 1 (display (left-fringe corfu--nil corfu-current))
- 1 2 (display (right-fringe corfu--nil corfu-current)))))
- (pos (posn-x-y pos))
- (width (+ (* width cw) (if graphic 0 (+ 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 (if graphic corfu-border-width 0))
- (x (max 0 (min (+ (car edge) (- (or (car pos) 0) ml (* cw off) border))
- (- (frame-pixel-width) width
- (if graphic (+ ml mr (* 2 border)) 0)))))
- (yb (+ (cadr edge) (or (cdr pos) 0) lh
- (static-if (< emacs-major-version 31) (window-tab-line-height) 0)))
- (y (if (> (+ yb (* corfu-count ch) lh lh) (frame-pixel-height))
- (- yb height lh border border)
- yb))
- (bmp (logxor (1- (ash 1 mr)) (1- (ash 1 bw)))))
- (setq left-fringe-width (if graphic ml 0) right-fringe-width (if graphic mr 0))
- ;; Define an inverted corfu--bar face
- (unless (equal (and (facep 'corfu--bar) (face-attribute 'corfu--bar :foreground))
- (face-attribute 'corfu-bar :background))
- (set-face-attribute (make-face 'corfu--bar) nil
- :foreground (face-attribute 'corfu-bar :background)))
- (unless (or (= right-fringe-width 0) (eq (get 'corfu--bar 'corfu--bmp) bmp))
- (put 'corfu--bar 'corfu--bmp bmp)
- (define-fringe-bitmap 'corfu--bar (vector (lognot bmp)) 1 mr '(top periodic))
- (define-fringe-bitmap 'corfu--nil [0] 1 1)
- ;; Fringe bitmaps require symbol face specification, define internal face.
- (set-face-attribute (make-face 'corfu--cbar) nil
- :inherit '(corfu--bar corfu-current)))
- (with-silent-modifications
- (delete-region (point-min) (point-max))
- (apply #'insert
- (cl-loop for row from 0 for line in lines collect
- (let ((str (concat marginl line
- (if (and lo (<= lo row (+ lo bar)))
- (if (eq row curr) cbar sbar)
- (and (eq row curr) cmargin))
- "\n")))
- (when (eq row curr)
- (add-face-text-property
- 0 (length str) 'corfu-current 'append str))
- str)))
- (goto-char (point-min)))
- (setq corfu--frame (corfu--make-frame corfu--frame x y width height))))))
-
-(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."
- (or (display-graphic-p) (featurep 'tty-child-frames)))
-
-(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* ((dep (corfu--metadata-get 'company-deprecated))
- (mf (let ((completion-extra-properties (nth 4 completion-in-region--data)))
- (run-hook-with-args-until-success 'corfu-margin-formatters corfu--metadata))))
- (setq cands
- (if-let* ((aff (corfu--metadata-get 'affixation-function)))
- (funcall aff cands)
- (if-let* ((ann (corfu--metadata-get '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."
- (corfu--preview-delete)
- ;; 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 ()
- "Exhibit Corfu UI."
- (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 corfu-on-exact-match
- (not (eq corfu-on-exact-match 'show))
- (equal corfu--candidates (list str))
- (not (consp (corfu--try-completion str table pred pt))))
- (if (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 (min (point-max) (+ 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 & initialized => Quit.
- (corfu--input (corfu-quit)))))
-
-(cl-defgeneric corfu--teardown (buffer)
- "Tear-down Corfu in BUFFER, which might be dead at this point."
- (corfu--popup-hide)
- (corfu--preview-delete)
- (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)
- (goto-char end)
- (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.
-If the currently selected candidate is previewed, jump to the input
-prompt instead. See `corfu-separator' for more details."
- (interactive)
- (if (not (corfu--preview-current-p))
- (insert corfu-separator)
- (corfu--goto -1)
- (unless (or (= (car completion-in-region--data) (point))
- (= (char-before) corfu-separator))
- (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.
- (pcase-let ((`(,_beg ,_end ,table ,pred . ,_) completion-in-region--data)
- (newstr (corfu--insert nil)))
- (and (test-completion newstr table pred)
- (or (not (consp (corfu--try-completion newstr table pred (length newstr))))
- ;; Additionally finish completion if at the end of a boundary,
- ;; even if other longer candidates match, since the user invoked
- ;; `corfu-complete' with an explicitly selected candidate!
- (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)))
- (pcase (corfu--try-completion str table pred pt)
- ('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 (corfu--try-completion newstr table pred newpt)))
- (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)))
-
-(defun corfu-send ()
- "Insert current candidate and send it when inside comint or eshell."
- (interactive)
- (corfu-insert)
- (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))))
-
-;;;###autoload
-(define-minor-mode corfu-mode
- "COmpletion in Region FUnction."
- :group 'corfu :keymap corfu-mode-map
- (cond
- (corfu-mode
- (when corfu-auto
- (require 'corfu-auto)
- (add-hook 'post-command-hook 'corfu-auto--post-command 10 '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-minibuffer t
- "Corfu should be enabled in the minibuffer by `global-corfu-mode'.
-The variable can either be t, nil or a custom predicate function. If
-the variable is set to t, Corfu is only enabled if the minibuffer has
-local `completion-at-point-functions'."
- :type '(choice (const t) (const nil) function)
- :group 'corfu)
-
-;;;###autoload
-(define-globalized-minor-mode global-corfu-mode
- corfu-mode corfu--on
- :group 'corfu
- :predicate t
- (remove-hook 'minibuffer-setup-hook #'corfu--minibuffer-on)
- (when (and global-corfu-mode global-corfu-minibuffer)
- (add-hook 'minibuffer-setup-hook #'corfu--minibuffer-on 100)))
-
-(defun corfu--on ()
- "Enable `corfu-mode' in the current buffer respecting `global-corfu-modes'."
- (unless (or noninteractive buffer-read-only (eq (aref (buffer-name) 0) ?\s))
- (corfu-mode)))
-
-(defun corfu--minibuffer-on ()
- "Enable `corfu-mode' in the minibuffer respecting `global-corfu-minibuffer'."
- (when (and global-corfu-minibuffer (not noninteractive)
- (if (functionp global-corfu-minibuffer)
- (funcall global-corfu-minibuffer)
- (local-variable-p 'completion-at-point-functions)))
- (corfu-mode)))
-
-;; 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-expand
- corfu-send corfu-insert-separator corfu-prompt-beginning corfu-prompt-end
- corfu-info-location corfu-info-documentation ;; autoloads in corfu-info.el
- corfu-quick-jump corfu-quick-insert corfu-quick-complete)) ;; autoloads in corfu-quick.el
- (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) (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 #'corfu-expand #'corfu-send)
-
-(with-eval-after-load 'corfu-terminal
- (when (featurep 'tty-child-frames)
- (display-warning 'corfu "`corfu-terminal' is not needed on Emacs 31")))
-
-(provide 'corfu)
-;;; corfu.el ends here