vertico-quick.el (5304B)
1 ;;; vertico-quick.el --- Quick keys for Vertico -*- lexical-binding: t -*- 2 3 ;; Copyright (C) 2021-2024 Free Software Foundation, Inc. 4 5 ;; Author: Daniel Mendler <mail@daniel-mendler.de> 6 ;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> 7 ;; Created: 2021 8 ;; Package-Requires: ((emacs "28.1") (compat "30") (vertico "1.9")) 9 ;; URL: https://github.com/minad/vertico 10 11 ;; This file is part of GNU Emacs. 12 13 ;; This program is free software: you can redistribute it and/or modify 14 ;; it under the terms of the GNU General Public License as published by 15 ;; the Free Software Foundation, either version 3 of the License, or 16 ;; (at your option) any later version. 17 18 ;; This program is distributed in the hope that it will be useful, 19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 ;; GNU General Public License for more details. 22 23 ;; You should have received a copy of the GNU General Public License 24 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 25 26 ;;; Commentary: 27 28 ;; This package is a Vertico extension, which prefixes candidates with 29 ;; quick keys. Typing these quick keys allows you to select the 30 ;; candidate in front of them. This is designed to be a faster 31 ;; alternative to selecting a candidate with `vertico-next' and 32 ;; `vertico-previous'. 33 ;; (keymap-set vertico-map "M-q" #'vertico-quick-insert) 34 ;; (keymap-set vertico-map "C-q" #'vertico-quick-exit) 35 36 ;;; Code: 37 38 (require 'vertico) 39 (eval-when-compile 40 (require 'cl-lib) 41 (require 'subr-x)) 42 43 (defface vertico-quick1 44 '((((class color) (min-colors 88) (background dark)) 45 :background "#0050af" :foreground "white" :inherit bold) 46 (((class color) (min-colors 88) (background light)) 47 :background "#7feaff" :foreground "black" :inherit bold) 48 (t :background "blue" :foreground "white" :inherit bold)) 49 "Face used for the first quick key." 50 :group 'vertico-faces) 51 52 (defface vertico-quick2 53 '((((class color) (min-colors 88) (background dark)) 54 :background "#7f1f7f" :foreground "white" :inherit bold) 55 (((class color) (min-colors 88) (background light)) 56 :background "#ffaaff" :foreground "black" :inherit bold) 57 (t :background "magenta" :foreground "white" :inherit bold)) 58 "Face used for the second quick key." 59 :group 'vertico-faces) 60 61 (defcustom vertico-quick1 "asdfgh" 62 "Single level quick keys." 63 :type 'string 64 :group 'vertico) 65 66 (defcustom vertico-quick2 "jkluionm" 67 "Two level quick keys." 68 :type 'string 69 :group 'vertico) 70 71 (defun vertico-quick--keys (two index start) 72 "Format quick keys prefix. 73 INDEX is the current candidate index. 74 START is the index of the first displayed candidate. 75 TWO is non-nil if two keys should be displayed." 76 (let ((fst (length vertico-quick1)) 77 (snd (length vertico-quick2)) 78 (idx (- index start))) 79 (if (>= idx fst) 80 (let ((first (elt vertico-quick2 (mod (/ (- idx fst) fst) snd))) 81 (second (elt vertico-quick1 (mod (- idx fst) fst)))) 82 (cond 83 ((eq first two) 84 (list 85 (concat " " (propertize (char-to-string second) 'face 'vertico-quick1)) 86 (cons second index))) 87 (two 88 (list " ")) 89 (t 90 (list 91 (concat (propertize (char-to-string first) 'face 'vertico-quick1) 92 (propertize (char-to-string second) 'face 'vertico-quick2)) 93 (cons first (list first)))))) 94 (let ((first (elt vertico-quick1 (mod idx fst)))) 95 (if two 96 (list " ") 97 (list 98 (concat (propertize (char-to-string first) 'face 'vertico-quick1) " ") 99 (cons first index))))))) 100 101 (defun vertico-quick--read (&optional first) 102 "Read quick key given FIRST pressed key." 103 (cl-letf* ((list nil) 104 (orig (symbol-function #'vertico--format-candidate)) 105 ((symbol-function #'vertico--format-candidate) 106 (lambda (cand prefix suffix index start) 107 (pcase-let ((`(,keys . ,events) (vertico-quick--keys first index start))) 108 (setq list (nconc events list)) 109 (if (bound-and-true-p vertico-flat-mode) 110 (setq keys (string-replace " " "" keys) 111 cand (string-trim cand) 112 cand (substring cand (min (length cand) (length keys)))) 113 (setq keys (concat keys (make-string (max 1 (- (length prefix) 2)) ?\s)))) 114 (funcall orig cand keys suffix index start))))) 115 (vertico--exhibit) 116 (alist-get (read-key) list))) 117 118 ;;;###autoload 119 (defun vertico-quick-jump () 120 "Jump to candidate using quick keys." 121 (interactive) 122 (if (= vertico--total 0) 123 (and (minibuffer-message "No match") nil) 124 (let ((idx (vertico-quick--read))) 125 (when (consp idx) (setq idx (vertico-quick--read (car idx)))) 126 (when idx (setq vertico--index idx))))) 127 128 ;;;###autoload 129 (defun vertico-quick-exit () 130 "Exit with candidate using quick keys." 131 (interactive) 132 (when (vertico-quick-jump) 133 (vertico-exit))) 134 135 ;;;###autoload 136 (defun vertico-quick-insert () 137 "Insert candidate using quick keys." 138 (interactive) 139 (when (vertico-quick-jump) 140 (vertico-insert))) 141 142 (provide 'vertico-quick) 143 ;;; vertico-quick.el ends here