config

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

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