dotemacs

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

corfu-indexed.el (4025B)


      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.27"))
     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 if
     30 ;; enabled via `corfu-indexed-mode'. It allows you to select candidates with
     31 ;; prefix arguments. This is designed to be a faster alternative to selecting a
     32 ;; candidate with `corfu-next' and `corfu-previous'.
     33 
     34 ;;; Code:
     35 
     36 (require 'corfu)
     37 (eval-when-compile
     38   (require 'cl-lib))
     39 
     40 (defface corfu-indexed
     41   '((default :height 0.75)
     42     (((class color) (min-colors 88) (background dark))
     43      :foreground "#f4f4f4" :background "#323232")
     44      (((class color) (min-colors 88) (background light))
     45      :foreground "#404148" :background "#d7d7d7")
     46     (t :background "black"))
     47   "Face used for the candidate index prefix."
     48   :group 'corfu-faces)
     49 
     50 (defcustom corfu-indexed-start 0
     51   "Start of the indexing."
     52   :group 'corfu
     53   :type 'integer)
     54 
     55 (defvar corfu-indexed--commands
     56   '(corfu-insert corfu-complete)
     57   "Commands that should be indexed.")
     58 
     59 (defun corfu-indexed--affixate (cands)
     60   "Advice for `corfu--affixate' which prefixes the CANDS with an index."
     61   (setq cands (cdr cands))
     62   (let* ((space #(" " 0 1 (face (:height 0.5 :inherit corfu-indexed))))
     63          (width (if (> (+ corfu-indexed-start (length cands)) 10) 2 1))
     64          (fmt (concat space
     65                       (propertize (format "%%%ds" width)
     66                                   'face 'corfu-indexed)
     67                       space))
     68          (align
     69           (propertize (make-string width ?\s)
     70                       'display
     71                       `(space :align-to (+ left ,(1+ width))))))
     72     (cl-loop for cand in cands for index from corfu-indexed-start do
     73       (setf (cadr cand)
     74             (concat
     75              (propertize " " 'display (format fmt index))
     76              align
     77              (cadr cand))))
     78     (cons t cands)))
     79 
     80 (defun corfu-indexed--handle-prefix (orig &rest args)
     81   "Handle prefix argument before calling ORIG function with ARGS."
     82   (if (and current-prefix-arg (called-interactively-p t))
     83       (let ((corfu--index (+ corfu--scroll
     84                              (- (prefix-numeric-value current-prefix-arg)
     85                                 corfu-indexed-start))))
     86         (if (or (< corfu--index 0)
     87                 (>= corfu--index corfu--total)
     88                 (>= corfu--index (+ corfu--scroll corfu-count)))
     89             (message "Out of range")
     90           (funcall orig)))
     91     (apply orig args)))
     92 
     93 ;;;###autoload
     94 (define-minor-mode corfu-indexed-mode
     95   "Prefix candidates with indices."
     96   :global t :group 'corfu
     97   (cond
     98    (corfu-indexed-mode
     99     (advice-add #'corfu--affixate :filter-return #'corfu-indexed--affixate)
    100     (dolist (cmd corfu-indexed--commands)
    101       (advice-add cmd :around #'corfu-indexed--handle-prefix)))
    102    (t
    103     (advice-remove #'corfu--affixate #'corfu-indexed--affixate)
    104     (dolist (cmd corfu-indexed--commands)
    105       (advice-remove cmd #'corfu-indexed--handle-prefix)))))
    106 
    107 (provide 'corfu-indexed)
    108 ;;; corfu-indexed.el ends here