add emacs config

This commit is contained in:
lucy 2026-08-21 23:49:25 +02:00
commit c1363180d7
761 changed files with 46444 additions and 0 deletions

View file

@ -0,0 +1,127 @@
;;; corfu-auto.el --- Auto completion -*- 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: 2022
;; Package-Requires: ((emacs "29.1") (compat "31") (corfu "2.14"))
;; URL: 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:
;; Automatically show the popup if `corfu-auto' is non-nil.
;;; Code:
(require 'corfu)
(defcustom corfu-auto-trigger ""
"Characters which trigger auto completion.
If a trigger character is detected `corfu-auto-prefix' is ignored."
:type 'string
:group 'corfu)
(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' and
`corfu-auto-trigger'."
:type 'natnum
:group 'corfu)
(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. Instead of reducing the delay too much, try
`corfu-auto-trigger' to trigger immediate completion after certain
characters."
:type 'float
:group 'corfu)
(defcustom corfu-auto-commands
'("self-insert-command\\'" "delete-backward-char\\'" "\\`backward-delete-char"
c-electric-colon c-electric-lt-gt c-electric-slash c-scope-operator)
"Commands which initiate auto completion.
The list can contain either command symbols or regular expressions."
:type '(repeat (choice regexp symbol))
:group 'corfu)
(defvar corfu-auto--timer (timer-create)
"Auto completion timer.")
(defun corfu-auto--complete-deferred (&optional tick)
"Initiate auto completion if TICK did not change."
(corfu--protect
(lambda ()
(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
(unless (seq-contains-p corfu-auto-trigger last-command-event)
corfu-auto-prefix)))
(`(,fun ,beg ,end ,table . ,plist)
(pcase-let* ((completion-in-region-mode-predicate
(lambda ()
(when-let* ((newbeg (car-safe (funcall fun))))
(= newbeg beg))))
(completion-extra-properties plist)
(pred (plist-get plist :predicate))
(state (plist-get plist :corfu--state))
(`(,str . ,pt) (alist-get 'corfu--input state))
(cands (alist-get 'corfu--candidates state)))
;; Bail out immediately for exactly matching candidates
;; if no further completion is possible.
(when (or (eq corfu-on-exact-match 'show)
(not (equal cands (list str)))
(consp (corfu--try-completion str table pred pt)))
(corfu--setup beg end table pred)
(corfu--exhibit)))))))))
(defun corfu-auto--post-command ()
"Post command hook which initiates auto completion."
(corfu--protect
(lambda ()
(cancel-timer corfu-auto--timer)
(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 (or (<= corfu-auto-delay 0)
(seq-contains-p corfu-auto-trigger last-command-event))
(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)))
(provide 'corfu-auto)
;;; corfu-auto.el ends here

Binary file not shown.

View file

@ -0,0 +1,260 @@
;;; corfu-autoloads.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*-
;; Generated by the `loaddefs-generate' function.
;; This file is part of GNU Emacs.
;;; Code:
(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
;;; Generated autoloads from corfu.el
(autoload 'corfu-mode "corfu" "\
COmpletion in Region FUnction.
This is a minor mode. If called interactively, toggle the `Corfu mode'
mode. If the prefix argument is positive, enable the mode, and if it is
zero or negative, disable the mode.
If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
mode if ARG is nil, omitted, or is a positive number. Disable the mode
if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate the variable `corfu-mode'.
The mode's hook is called both when the mode is enabled and when it is
disabled.
(fn &optional ARG)" t)
(put 'global-corfu-mode 'globalized-minor-mode t)
(defvar global-corfu-mode nil "\
Non-nil if Global Corfu mode is enabled.
See the `global-corfu-mode' command
for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-corfu-mode'.")
(custom-autoload 'global-corfu-mode "corfu" nil)
(autoload 'global-corfu-mode "corfu" "\
Toggle Corfu mode in all buffers.
With prefix ARG, enable Global Corfu mode if ARG is positive;
otherwise, disable it.
If called from Lisp, toggle the mode if ARG is `toggle'.
Enable the mode if ARG is nil, omitted, or is a positive number.
Disable the mode if ARG is a negative number.
Corfu mode is enabled in all buffers where `corfu--on' would do it.
See `corfu-mode' for more information on Corfu mode.
`global-corfu-modes' is used to control which modes this minor mode is
used in.
(fn &optional ARG)" t)
(defvar global-corfu-modes t "\
Which major modes `corfu-mode' is switched on in.
This variable can be either t (all major modes), nil (no major modes),
or a list of modes and (not modes) to switch use this minor mode or
not. For instance
(c-mode (not message-mode mail-mode) text-mode)
means \"use this mode in all modes derived from `c-mode', don't use in
modes derived from `message-mode' or `mail-mode', but do use in other
modes derived from `text-mode'\". An element with value t means \"use\"
and nil means \"don't use\". There's an implicit nil at the end of the
list.")
(custom-autoload 'global-corfu-modes "corfu" t)
(register-definition-prefixes "corfu" '("corfu-" "global-corfu-minibuffer"))
;;; Generated autoloads from corfu-auto.el
(register-definition-prefixes "corfu-auto" '("corfu-auto-"))
;;; Generated autoloads from corfu-echo.el
(defvar corfu-echo-mode nil "\
Non-nil if Corfu-Echo mode is enabled.
See the `corfu-echo-mode' command
for a description of this minor mode.")
(custom-autoload 'corfu-echo-mode "corfu-echo" nil)
(autoload 'corfu-echo-mode "corfu-echo" "\
Show candidate documentation in echo area.
This is a global minor mode. If called interactively, toggle the
`Corfu-Echo mode' mode. If the prefix argument is positive, enable the
mode, and if it is zero or negative, disable the mode.
If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
mode if ARG is nil, omitted, or is a positive number. Disable the mode
if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='corfu-echo-mode)'.
The mode's hook is called both when the mode is enabled and when it is
disabled.
(fn &optional ARG)" t)
(register-definition-prefixes "corfu-echo" '("corfu-echo-"))
;;; Generated autoloads from corfu-history.el
(defvar corfu-history-mode nil "\
Non-nil if Corfu-History mode is enabled.
See the `corfu-history-mode' command
for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `corfu-history-mode'.")
(custom-autoload 'corfu-history-mode "corfu-history" nil)
(autoload 'corfu-history-mode "corfu-history" "\
Save completion history and sort candidates by history.
This is a global minor mode. If called interactively, toggle the
`Corfu-History mode' mode. If the prefix argument is positive, enable
the mode, and if it is zero or negative, disable the mode.
If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
mode if ARG is nil, omitted, or is a positive number. Disable the mode
if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='corfu-history-mode)'.
The mode's hook is called both when the mode is enabled and when it is
disabled.
(fn &optional ARG)" t)
(register-definition-prefixes "corfu-history" '("corfu-history"))
;;; Generated autoloads from corfu-indexed.el
(defvar corfu-indexed-mode nil "\
Non-nil if Corfu-Indexed mode is enabled.
See the `corfu-indexed-mode' command
for a description of this minor mode.")
(custom-autoload 'corfu-indexed-mode "corfu-indexed" nil)
(autoload 'corfu-indexed-mode "corfu-indexed" "\
Prefix candidates with indices.
This is a global minor mode. If called interactively, toggle the
`Corfu-Indexed mode' mode. If the prefix argument is positive, enable
the mode, and if it is zero or negative, disable the mode.
If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
mode if ARG is nil, omitted, or is a positive number. Disable the mode
if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='corfu-indexed-mode)'.
The mode's hook is called both when the mode is enabled and when it is
disabled.
(fn &optional ARG)" t)
(register-definition-prefixes "corfu-indexed" '("corfu-indexed-"))
;;; Generated autoloads from corfu-info.el
(autoload 'corfu-info-documentation "corfu-info" "\
Show documentation of current candidate.
If called with a prefix ARG, the buffer is persistent.
(fn &optional ARG)" t)
(autoload 'corfu-info-location "corfu-info" "\
Show location of current candidate.
If called with a prefix ARG, the buffer is persistent.
(fn &optional ARG)" t)
(register-definition-prefixes "corfu-info" '("corfu-info--"))
;;; Generated autoloads from corfu-mouse.el
(defvar corfu-mouse-mode nil "\
Non-nil if Corfu-Mouse mode is enabled.
See the `corfu-mouse-mode' command
for a description of this minor mode.")
(custom-autoload 'corfu-mouse-mode "corfu-mouse" nil)
(autoload 'corfu-mouse-mode "corfu-mouse" "\
Mouse support, scrolling and clickable candidates.
This is a global minor mode. If called interactively, toggle the
`Corfu-Mouse mode' mode. If the prefix argument is positive, enable the
mode, and if it is zero or negative, disable the mode.
If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
mode if ARG is nil, omitted, or is a positive number. Disable the mode
if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='corfu-mouse-mode)'.
The mode's hook is called both when the mode is enabled and when it is
disabled.
(fn &optional ARG)" t)
(register-definition-prefixes "corfu-mouse" '("corfu-mouse-"))
;;; Generated autoloads from corfu-popupinfo.el
(defvar corfu-popupinfo-mode nil "\
Non-nil if Corfu-Popupinfo mode is enabled.
See the `corfu-popupinfo-mode' command
for a description of this minor mode.")
(custom-autoload 'corfu-popupinfo-mode "corfu-popupinfo" nil)
(autoload 'corfu-popupinfo-mode "corfu-popupinfo" "\
Show candidate documentation in a popup.
This is a global minor mode. If called interactively, toggle the
`Corfu-Popupinfo mode' mode. If the prefix argument is positive, enable
the mode, and if it is zero or negative, disable the mode.
If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
mode if ARG is nil, omitted, or is a positive number. Disable the mode
if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='corfu-popupinfo-mode)'.
The mode's hook is called both when the mode is enabled and when it is
disabled.
(fn &optional ARG)" t)
(register-definition-prefixes "corfu-popupinfo" '("corfu-popupinfo-"))
;;; Generated autoloads from corfu-quick.el
(autoload 'corfu-quick-jump "corfu-quick" "\
Jump to candidate using quick keys." t)
(autoload 'corfu-quick-insert "corfu-quick" "\
Insert candidate using quick keys." t)
(autoload 'corfu-quick-complete "corfu-quick" "\
Complete candidate using quick keys." t)
(register-definition-prefixes "corfu-quick" '("corfu-quick"))
;;; End of scraped data
(provide 'corfu-autoloads)
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; no-native-compile: t
;; coding: utf-8-emacs-unix
;; End:
;;; corfu-autoloads.el ends here

View file

@ -0,0 +1,108 @@
;;; corfu-echo.el --- Show candidate documentation in echo area -*- 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: 2022
;; Package-Requires: ((emacs "29.1") (compat "31") (corfu "2.14"))
;; URL: 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)))
(if-let* (((not (minibufferp)))
(delay (if (consp corfu-echo-delay)
(funcall (if corfu-echo--message #'cdr #'car)
corfu-echo-delay)
corfu-echo-delay))
(fun (corfu--metadata-get '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

Binary file not shown.

View file

@ -0,0 +1,113 @@
;;; corfu-history.el --- Sorting by history for Corfu -*- lexical-binding: t -*-
;; Copyright (C) 2022-2026 Free Software Foundation, Inc.
;; Author: Daniel Mendler <mail@daniel-mendler.de>
;; Maintainer: Daniel Mendler <mail@daniel-mendler.de>
;; Created: 2022
;; Package-Requires: ((emacs "29.1") (compat "31") (corfu "2.14"))
;; URL: 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.
;; The recently selected candidates are stored in the `corfu-history' variable.
;; If `history-delete-duplicates' is nil, duplicate elements are ranked higher
;; with exponential decay. In order to save the history across Emacs sessions,
;; enable `savehist-mode'.
;;
;; (corfu-history-mode)
;; (savehist-mode)
;;; 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.")
(defcustom corfu-history-duplicate 10
"History position shift for duplicate history elements.
The more often a duplicate element occurs in the history, the earlier it
appears in the completion list. The shift decays exponentially with
`corfu-history-decay'. Note that duplicates occur only if
`history-delete-duplicates' is disabled."
:type 'number
:group 'corfu)
(defcustom corfu-history-decay 10
"Exponential decay for the position shift of duplicate elements.
The shift will decay away after `corfu-history-duplicate' times
`corfu-history-decay' history elements."
:type 'number
:group 'corfu)
(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
(let ((ht (make-hash-table :test #'equal :size (length corfu-history)))
(decay (/ -1.0 (* corfu-history-duplicate corfu-history-decay))))
(cl-loop for elem in corfu-history for idx from 0
for r = (if-let* ((r (gethash elem ht)))
;; Reduce duplicate rank with exponential decay.
(- r (round (* corfu-history-duplicate (exp (* decay idx)))))
;; Never outrank the most recent element.
(if (= idx 0) (/ most-negative-fixnum 2) idx))
do (puthash elem r ht))
(setq corfu-history--hash ht)))
(cl-loop for ht = corfu-history--hash for max = most-positive-fixnum
for cand on cands do
(setcar cand (cons (car cand) (gethash (car cand) ht max))))
(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
"Save completion history and sort candidates 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)
(unless (or (not (bound-and-true-p savehist-mode))
(memq 'corfu-history (bound-and-true-p savehist-ignored-variables)))
(defvar savehist-minibuffer-history-variables)
(add-to-list 'savehist-minibuffer-history-variables 'corfu-history))
(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

Binary file not shown.

View file

@ -0,0 +1,96 @@
;;; corfu-indexed.el --- Select indexed candidates -*- lexical-binding: t -*-
;; Copyright (C) 2022-2026 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
;; Package-Requires: ((emacs "29.1") (compat "31") (corfu "2.14"))
;; URL: 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

Binary file not shown.

View file

@ -0,0 +1,116 @@
;;; corfu-info.el --- Show candidate information in separate buffer -*- lexical-binding: t -*-
;; Copyright (C) 2022-2026 Free Software Foundation, Inc.
;; Author: Daniel Mendler <mail@daniel-mendler.de>
;; Maintainer: Daniel Mendler <mail@daniel-mendler.de>
;; Created: 2022
;; Package-Requires: ((emacs "29.1") (compat "31") (corfu "2.14"))
;; URL: 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)
(require 'cl-lib))
(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"))
(cl-letf* ((cand (nth corfu--index corfu--candidates))
(cand-str (substring-no-properties cand))
((symbol-function #'help-buffer) ;; Work around bug#79792
(lambda () (get-buffer-create " *corfu-info*"))))
(if-let* ((fun (corfu--metadata-get '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 info: %s*" cand-str)))
(or (cdr-safe res) (point-min)))
(user-error "No documentation available for `%s'" cand-str))))
;;;###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))
(cand-str (substring-no-properties cand)))
(if-let* ((fun (corfu--metadata-get '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-str)))
(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-str))))
(provide 'corfu-info)
;;; corfu-info.el ends here

Binary file not shown.

View file

@ -0,0 +1,93 @@
;;; corfu-mouse.el --- Mouse support -*- lexical-binding: t -*-
;; Copyright (C) 2026 Free Software Foundation, Inc.
;; Author: Daniel Mendler <mail@daniel-mendler.de>
;; Maintainer: Daniel Mendler <mail@daniel-mendler.de>
;; Created: 2026
;; Package-Requires: ((emacs "29.1") (compat "31") (corfu "2.14"))
;; URL: 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 adds mouse support if enabled
;; via `corfu-mouse-mode'. Known limitations: The mode does not work on
;; Windows. On the terminal `xterm-mouse-mode' needs to be enabled, but
;; clicking is still not working. Improvements welcome!
;;; Code:
(require 'corfu)
(eval-when-compile
(require 'cl-lib))
(defface corfu-mouse
'((t :inherit highlight))
"Face used for mouse highlighting."
:group 'corfu-faces)
(defvar-keymap corfu-mouse-map
:doc "Additional keymap activated by `corfu-mouse-mode'."
:parent corfu--mouse-ignore-map
"<mouse-1>" #'corfu-mouse-complete
"<mouse-2>" #'corfu-mouse-complete
"<wheel-up>" #'corfu-previous
"<wheel-down>" #'corfu-next)
(fset 'corfu-mouse-map corfu-mouse-map)
;;;###autoload
(define-minor-mode corfu-mouse-mode
"Mouse support, scrolling and clickable candidates."
:global t :group 'corfu)
(defun corfu-mouse-complete ()
"Call `corfu-complete' with candidate at mouse position."
(declare (completion ignore))
(interactive)
(when-let* ((row (cdr (posn-col-row (event-end last-input-event))))
((fixnump row))
(index (+ corfu--scroll row))
((and (>= index 0) (< index corfu--total))))
(corfu--goto index)
(corfu-complete)))
(cl-defmethod corfu--popup-show :around (pos off width lines
&context (corfu-mouse-mode (eql t))
&rest args)
(setq-local mwheel-coalesce-scroll-events t)
(apply #'cl-call-next-method pos off width
(cl-loop
with extend = (if (display-graphic-p)
#(" " 0 1 (display (space :align-to right)))
#(" " 0 1 (display (space :align-to (- right 1)))))
for line in lines
for padded = (concat line extend)
do (add-text-properties
0 (length padded)
'(mouse-face corfu-mouse keymap corfu-mouse-map)
padded)
collect padded)
args))
(cl-defmethod corfu--teardown :before (buf &context (corfu-mouse-mode (eql t)))
(when (buffer-live-p buf)
(with-current-buffer buf
(kill-local-variable 'mwheel-coalesce-scroll-events))))
(provide 'corfu-mouse)
;;; corfu-mouse.el ends here

Binary file not shown.

View file

@ -0,0 +1,11 @@
;; -*- no-byte-compile: t; lexical-binding: nil -*-
(define-package "corfu" "2.14"
"COmpletion in Region FUnction."
'((emacs "29.1")
(compat "31"))
:url "https://github.com/minad/corfu"
:commit "75be36fe63e78c63ac71c32039ab07836bd532ac"
:revdesc "2.14-0-g75be36fe63e7"
:keywords '("abbrev" "convenience" "matching" "completion" "text")
:authors '(("Daniel Mendler" . "mail@daniel-mendler.de"))
:maintainers '(("Daniel Mendler" . "mail@daniel-mendler.de")))

View file

@ -0,0 +1,532 @@
;;; corfu-popupinfo.el --- Candidate information popup for Corfu -*- lexical-binding: t -*-
;; Copyright (C) 2021-2026 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
;; Package-Requires: ((emacs "29.1") (compat "31") (corfu "2.14"))
;; URL: 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.
In order to use a smaller face for the popupinfo, use for example:
(set-face-attribute \\='corfu-popupinfo nil :height 0.8)"
:group 'corfu-faces)
(defcustom corfu-popupinfo-delay '(2.0 . 0.5)
"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 nil
"Hide the popup during the transition between candidates."
:type 'boolean
:group 'corfu)
(defcustom corfu-popupinfo-margin-width 1
"Margin at the left and right side of the popup."
:type 'natnum
: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 by `corfu-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)
(word-wrap . t)
(char-property-alias-alist (face font-lock-face)))
"Additional child frame buffer parameters.
It is recommended to avoid changing these 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--geometry nil
"Geometry of the candidate popup.
The list has the form (LEFT TOP WIDTH HIEGHT) with the values in pixels.")
(defvar corfu-popupinfo--lock-dir nil
"Locked position direction of the info popup.")
(defconst corfu-popupinfo--buffer " *corfu-popupinfo*"
"Buffer used by the popup.")
(defconst corfu-popupinfo--initial-state
(mapcar
(lambda (k) (cons k (symbol-value k)))
'(corfu-popupinfo--candidate
corfu-popupinfo--geometry
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
((fun (corfu--metadata-get '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
(list
(static-if (>= emacs-major-version 30)
'global-font-lock-mode-enable-in-buffer
'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 (bound-and-true-p hl-line-mode) (fboundp 'hl-line-highlight))
(hl-line-highlight))
(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 (corfu--metadata-get 'company-doc-buffer))
(res (save-excursion
(cl-letf (((symbol-function #'help-buffer) ;; Work around bug#79792
(lambda () (get-buffer-create " *corfu-info*")))
(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)))))
(when (and (bound-and-true-p hl-line-mode) (fboundp 'hl-line-highlight))
(hl-line-highlight))
(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--compute-size ()
"Compute popup size from buffer content and return as pair."
(let* ((cw (default-font-width))
(lh (default-line-height))
(margin (* cw (* 2 corfu-popupinfo-margin-width)))
(max-height (* lh corfu-popupinfo-max-height))
(max-width (* cw corfu-popupinfo-max-width)))
(or (when corfu-popupinfo-resize
(with-current-buffer corfu-popupinfo--buffer
(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--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--possible-areas (ps)
"Calculate possible display areas for the info popup.
PS is the pixel size of the popup. Return a list of left area, right
area and vertical area."
(pcase-let*
((lh (default-line-height))
(`(,pw . ,ph) ps)
(border (if (display-graphic-p corfu--frame) corfu-border-width 0))
(parent (frame-parent corfu--frame))
(pfw (frame-pixel-width parent))
(pfh (frame-pixel-height parent))
(`(,cfx ,cfy ,cfw ,cfh) (frame-parameter corfu--frame 'corfu--geometry))
(cfw (+ cfw (* 2 border)
(frame-parameter corfu--frame 'left-fringe)
(frame-parameter corfu--frame 'right-fringe)))
(cfh (+ cfh (* 2 border)))
;; Candidates popup below input
(below (>= cfy (+ lh (cadr (window-inside-pixel-edges))
(static-if (< emacs-major-version 31)
(window-tab-line-height) 0)
(or (cdr (posn-x-y (posn-at-point (point)))) 0))))
;; Popups aligned at top
(top-aligned (or below (< ph cfh)))
;; Left display area
(ahy (if top-aligned cfy (max 0 (- (+ cfy cfh) border border ph))))
(ahh (min ph (if top-aligned (- pfh cfy) (- (+ cfy cfh) border border))))
(al (list (max 0 (- cfx pw border)) ahy
(min (- cfx border) pw) ahh 'left))
;; Right display area
(arx (+ cfx cfw (- border)))
(ar (list arx ahy (min (- pfw arx border border) pw) ahh 'right))
;; Vertical display area
(avw (min pw (- pfw cfx border border)))
(av (if below
(list cfx (+ cfy cfh (- border)) avw (min (- pfh cfy cfh border) ph) 'vertical)
(let ((h (min (- cfy border border) ph)))
(list cfx (max 0 (- cfy h border)) avw h 'vertical)))))
(list al ar av)))
(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 ((`(,al ,ar ,av) (corfu-popupinfo--possible-areas ps)))
(unless (and corfu-popupinfo--lock-dir
(corfu-popupinfo--fits-p
(cons (* (default-font-width) corfu-popupinfo-min-width)
(* (default-line-height) 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 (corfu-popupinfo--visible-p corfu--frame)
(let* ((cand-changed
(not (and (corfu-popupinfo--visible-p)
(equal-including-properties candidate corfu-popupinfo--candidate))))
(new-geo (frame-parameter corfu--frame 'corfu--geometry))
(geo-changed (not (equal new-geo corfu-popupinfo--geometry))))
(when cand-changed
(if-let* ((content (funcall corfu-popupinfo--function candidate)))
(with-current-buffer (corfu--make-buffer corfu-popupinfo--buffer)
(with-silent-modifications
(erase-buffer)
(insert content)
(goto-char (point-min)))
(dolist (var corfu-popupinfo--buffer-parameters)
(set-local (car var) (cdr var)))
(setq left-margin-width corfu-popupinfo-margin-width
right-margin-width corfu-popupinfo-margin-width)
(when-let* ((m (memq 'corfu-default (alist-get 'default face-remapping-alist))))
(setcar m 'corfu-popupinfo)))
(corfu-popupinfo--hide)
(setq cand-changed nil geo-changed nil)))
(when (or cand-changed geo-changed)
(pcase-let* ((old-frame corfu-popupinfo--frame)
(`(,area-x ,area-y ,area-w ,area-h ,area-d)
(corfu-popupinfo--area
(if cand-changed
(corfu-popupinfo--compute-size)
(let ((old (frame-parameter old-frame 'corfu--geometry)))
(cons (nth 2 old) (nth 3 old)))))))
(setq corfu-popupinfo--frame
(with-current-buffer corfu-popupinfo--buffer
(corfu--make-frame corfu-popupinfo--frame
area-x area-y area-w area-h))
corfu-popupinfo--toggle t
corfu-popupinfo--lock-dir area-d
corfu-popupinfo--candidate candidate
corfu-popupinfo--geometry new-geo)
;; 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?
(unless (eq old-frame corfu-popupinfo--frame)
(set-window-buffer (frame-root-window corfu-popupinfo--frame)
corfu-popupinfo--buffer)))))))
(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 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--buffer
(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--buffer
(scroll-up-command 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")
(if (corfu-popupinfo--visible-p)
(with-selected-frame corfu-popupinfo--frame
(with-current-buffer corfu-popupinfo--buffer
(scroll-down-command n)))
(scroll-other-window-down n)))
(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) "-+")))
(substring-no-properties 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
"Show candidate documentation in a popup."
:global t :group 'corfu)
(cl-defmethod corfu--exhibit :after (&context (corfu-popupinfo-mode (eql t)))
(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* ((old-cand corfu-popupinfo--candidate)
(new-cand (nth corfu--index corfu--candidates))
(cand-changed (not (equal-including-properties new-cand old-cand)))
(delay (if (consp corfu-popupinfo-delay)
(funcall (if (eq corfu-popupinfo--toggle 'init) #'car #'cdr)
corfu-popupinfo-delay)
corfu-popupinfo-delay)))
(cond
((and delay corfu-popupinfo--toggle)
(when (and (corfu-popupinfo--visible-p) (> delay 0))
(cond
((and corfu-popupinfo-hide cand-changed)
(corfu-popupinfo--hide))
(old-cand
(corfu-popupinfo--show old-cand))))
(setq corfu-popupinfo--timer
(run-at-time delay nil #'corfu-popupinfo--show new-cand)))
(cand-changed
(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))
;; 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

Binary file not shown.

View file

@ -0,0 +1,141 @@
;;; corfu-quick.el --- Quick keys for Corfu -*- lexical-binding: t -*-
;; Copyright (C) 2022-2026 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
;; Package-Requires: ((emacs "29.1") (compat "31") (corfu "2.14"))
;; URL: 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
(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
(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)
(orig (symbol-function #'corfu--format-candidates))
((symbol-function #'corfu--format-candidates)
(lambda (cands)
(setq cands (funcall orig cands))
(cl-loop for cand in-ref (nth 2 cands) for index from 0 do
(pcase-let ((`(,keys . ,events) (corfu-quick--keys first index)))
(setf list (nconc events list)
cand (concat keys (substring cand (min (length cand) (length keys)))))))
cands)))
(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)))
(provide 'corfu-quick)
;;; corfu-quick.el ends here

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.