vertico-quick.el (5513B)
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 ;; Version: 1.8 9 ;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4") (vertico "1.8")) 10 ;; Homepage: https://github.com/minad/vertico 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 <https://www.gnu.org/licenses/>. 26 27 ;;; Commentary: 28 29 ;; This package is a Vertico extension, which prefixes candidates with 30 ;; quick keys. Typing these quick keys allows you to select the 31 ;; candidate in front of them. This is designed to be a faster 32 ;; alternative to selecting a candidate with `vertico-next' and 33 ;; `vertico-previous'. 34 ;; (keymap-set vertico-map "M-q" #'vertico-quick-insert) 35 ;; (keymap-set vertico-map "C-q" #'vertico-quick-exit) 36 37 ;;; Code: 38 39 (require 'vertico) 40 (eval-when-compile 41 (require 'cl-lib) 42 (require 'subr-x)) 43 44 (defface vertico-quick1 45 '((((class color) (min-colors 88) (background dark)) 46 :background "#0050af" :foreground "white" :inherit bold) 47 (((class color) (min-colors 88) (background light)) 48 :background "#7feaff" :foreground "black" :inherit bold) 49 (t :background "blue" :foreground "white" :inherit bold)) 50 "Face used for the first quick key." 51 :group 'vertico-faces) 52 53 (defface vertico-quick2 54 '((((class color) (min-colors 88) (background dark)) 55 :background "#7f1f7f" :foreground "white" :inherit bold) 56 (((class color) (min-colors 88) (background light)) 57 :background "#ffaaff" :foreground "black" :inherit bold) 58 (t :background "magenta" :foreground "white" :inherit bold)) 59 "Face used for the second quick key." 60 :group 'vertico-faces) 61 62 (defcustom vertico-quick1 "asdfgh" 63 "Single level quick keys." 64 :type 'string 65 :group 'vertico) 66 67 (defcustom vertico-quick2 "jkluionm" 68 "Two level quick keys." 69 :type 'string 70 :group 'vertico) 71 72 (defun vertico-quick--keys (two index start) 73 "Format quick keys prefix. 74 INDEX is the current candidate index. 75 START is the index of the first displayed candidate. 76 TWO is non-nil if two keys should be displayed." 77 (let ((fst (length vertico-quick1)) 78 (snd (length vertico-quick2)) 79 (idx (- index start))) 80 (if (>= idx fst) 81 (let ((first (elt vertico-quick2 (mod (/ (- idx fst) fst) snd))) 82 (second (elt vertico-quick1 (mod (- idx fst) fst)))) 83 (cond 84 ((eq first two) 85 (list 86 (concat " " (propertize (char-to-string second) 'face 'vertico-quick1)) 87 (cons second index))) 88 (two 89 (list " ")) 90 (t 91 (list 92 (concat (propertize (char-to-string first) 'face 'vertico-quick1) 93 (propertize (char-to-string second) 'face 'vertico-quick2)) 94 (cons first (list first)))))) 95 (let ((first (elt vertico-quick1 (mod idx fst)))) 96 (if two 97 (list " ") 98 (list 99 (concat (propertize (char-to-string first) 'face 'vertico-quick1) " ") 100 (cons first index))))))) 101 102 (defun vertico-quick--read (&optional first) 103 "Read quick key given FIRST pressed key." 104 (cl-letf* ((list nil) 105 (orig (symbol-function #'vertico--format-candidate)) 106 ((symbol-function #'vertico--format-candidate) 107 (lambda (cand prefix suffix index start) 108 (pcase-let ((`(,keys . ,events) (vertico-quick--keys first index start))) 109 (setq list (nconc events list)) 110 (if (bound-and-true-p vertico-flat-mode) 111 (setq keys (string-replace " " "" keys) 112 cand (string-trim cand) 113 cand (substring cand (min (length cand) (length keys)))) 114 (setq keys (concat keys (make-string (max 1 (- (length prefix) 2)) ?\s)))) 115 (funcall orig cand keys suffix index start))))) 116 (vertico--exhibit) 117 (alist-get (read-key) list))) 118 119 ;;;###autoload 120 (defun vertico-quick-jump () 121 "Jump to candidate using quick keys." 122 (interactive) 123 (if (= vertico--total 0) 124 (and (minibuffer-message "No match") nil) 125 (let ((idx (vertico-quick--read))) 126 (when (consp idx) (setq idx (vertico-quick--read (car idx)))) 127 (when idx (setq vertico--index idx))))) 128 129 ;;;###autoload 130 (defun vertico-quick-exit () 131 "Exit with candidate using quick keys." 132 (interactive) 133 (when (vertico-quick-jump) 134 (vertico-exit))) 135 136 ;;;###autoload 137 (defun vertico-quick-insert () 138 "Insert candidate using quick keys." 139 (interactive) 140 (when (vertico-quick-jump) 141 (vertico-insert))) 142 143 ;; Emacs 28: Do not show Vertico commands in M-X 144 (dolist (sym '(vertico-quick-jump vertico-quick-exit vertico-quick-insert)) 145 (put sym 'completion-predicate #'vertico--command-p)) 146 147 (provide 'vertico-quick) 148 ;;; vertico-quick.el ends here