corfu-indexed.el (3753B)
1 ;;; corfu-indexed.el --- Select indexed candidates -*- lexical-binding: t -*- 2 3 ;; Copyright (C) 2022 Free Software Foundation, Inc. 4 5 ;; Author: Luis Henriquez-Perez <luis@luishp.xyz>, Daniel Mendler <mail@daniel-mendler.de> 6 ;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> 7 ;; Created: 2022 8 ;; Version: 0.1 9 ;; Package-Requires: ((emacs "27.1") (corfu "0.23")) 10 ;; Homepage: https://github.com/minad/corfu 11 12 ;; This file is part of GNU Emacs. 13 14 ;; This program is free software: you can redistribute it and/or modify 15 ;; it under the terms of the GNU General Public License as published by 16 ;; the Free Software Foundation, either version 3 of the License, or 17 ;; (at your option) any later version. 18 19 ;; This program is distributed in the hope that it will be useful, 20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 ;; GNU General Public License for more details. 23 24 ;; You should have received a copy of the GNU General Public License 25 ;; along with this program. If not, see <http://www.gnu.org/licenses/>. 26 27 ;;; Commentary: 28 29 ;; This package is a Corfu extension, which prefixes candidates with indices and 30 ;; allows you to select with prefix arguments. This is designed to be a faster 31 ;; alternative to selecting a candidate with `corfu-next' and `corfu-previous'. 32 33 ;;; Code: 34 35 (require 'corfu) 36 (eval-when-compile 37 (require 'cl-lib)) 38 39 (defface corfu-indexed 40 '((default :height 0.75) 41 (((class color) (min-colors 88) (background dark)) 42 :foreground "#f4f4f4" :background "#323232") 43 (((class color) (min-colors 88) (background light)) 44 :foreground "#404148" :background "#d7d7d7") 45 (t :background "black")) 46 "Face used for the candidate index prefix." 47 :group 'corfu-faces) 48 49 (defvar corfu-indexed--commands 50 '(corfu-insert corfu-complete) 51 "Commands that should be indexed.") 52 53 (defun corfu-indexed--affixate (cands) 54 "Advice for `corfu--affixate' which prefixes the CANDS with an index." 55 (setq cands (cdr cands)) 56 (let* ((space #(" " 0 1 (face (:height 0.5 :inherit corfu-indexed)))) 57 (width (if (> (length cands) 10) 2 1)) 58 (fmt (concat space 59 (propertize (format "%%%ds" width) 60 'face 'corfu-indexed) 61 space)) 62 (align 63 (propertize (make-string width ?\s) 64 'display 65 `(space :align-to (+ left ,(1+ width)))))) 66 (cl-loop for cand in cands for index from 0 do 67 (setf (cadr cand) 68 (concat 69 (propertize " " 'display (format fmt index)) 70 align 71 (cadr cand)))) 72 (cons t cands))) 73 74 (defun corfu-indexed--handle-prefix (orig &rest args) 75 "Handle prefix argument before calling ORIG function with ARGS." 76 (if (and current-prefix-arg (called-interactively-p t)) 77 (let ((corfu--index (+ corfu--scroll (prefix-numeric-value current-prefix-arg)))) 78 (if (or (< corfu--index 0) 79 (>= corfu--index corfu--total) 80 (>= corfu--index (+ corfu--scroll corfu-count))) 81 (message "Out of range") 82 (funcall orig))) 83 (apply orig args))) 84 85 ;;;###autoload 86 (define-minor-mode corfu-indexed-mode 87 "Prefix candidates with indices." 88 :global t :group 'corfu 89 (cond 90 (corfu-indexed-mode 91 (advice-add #'corfu--affixate :filter-return #'corfu-indexed--affixate) 92 (dolist (cmd corfu-indexed--commands) 93 (advice-add cmd :around #'corfu-indexed--handle-prefix))) 94 (t 95 (advice-remove #'corfu--affixate #'corfu-indexed--affixate) 96 (dolist (cmd corfu-indexed--commands) 97 (advice-remove cmd #'corfu-indexed--handle-prefix))))) 98 99 (provide 'corfu-indexed) 100 ;;; corfu-indexed.el ends here