config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

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