branch: externals/vertico commit 489e87306535f2353eb4877593dadd03a057a850 Author: Daniel Mendler <m...@daniel-mendler.de> Commit: Daniel Mendler <m...@daniel-mendler.de>
Add vertico-quick extension --- README.org | 14 ++--- extensions/vertico-quick.el | 132 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 7 deletions(-) diff --git a/README.org b/README.org index ab46747..d7529ff 100644 --- a/README.org +++ b/README.org @@ -156,6 +156,7 @@ - [[https://github.com/minad/vertico/blob/main/extensions/vertico-buffer.el][vertico-buffer.el]]: Enable =vertico-buffer-mode= to display Vertico in a separate buffer - [[https://github.com/minad/vertico/blob/main/extensions/vertico-directory.el][vertico-directory.el]]: Commands for Ido-like directory navigation - [[https://github.com/minad/vertico/blob/main/extensions/vertico-flat.el][vertico-flat.el]]: Enable =vertico-flat-mode= to enable a flat, horizontal display + - [[https://github.com/minad/vertico/blob/main/extensions/vertico-quick.el][vertico-quick.el]]: Select using Avy-style quick keys - [[https://github.com/minad/vertico/blob/main/extensions/vertico-repeat.el][vertico-repeat.el]]: The command =vertico-repeat= repeats the last completion session - [[https://github.com/minad/vertico/blob/main/extensions/vertico-reverse.el][vertico-reverse.el]]: Enable =vertico-reverse-mode= to reverse the display @@ -214,13 +215,12 @@ with Emacs. There are at least two other interactive completion UIs, which follow a similar philosophy: - - [[https://github.com/raxod502/selectrum][Selectrum]]: Selectrum has a similar UI as Vertico. Selectrum is significantly - more complex and not fully compatible with every Emacs completion command - ([[https://github.com/raxod502/selectrum/issues/481][Issue #481]]), since it uses its own filtering infrastructure, which deviates - from the standard Emacs completion facilities. Selectrum supports additional - Avy-style quick keys. Vertico additionally has the ability to cycle over - candidates, offers more commands for grouping support and comes with - optional [[#extensions][extensions]]. + - [[https://github.com/raxod502/selectrum][Selectrum]]: Selectrum has a similar UI as Vertico. Selectrum is more complex + and not fully compatible with every Emacs completion command ([[https://github.com/raxod502/selectrum/issues/481][Issue #481]]), + since it uses its own filtering infrastructure, which deviates from the + standard Emacs completion facilities. Vertico additionally has the ability + to cycle over candidates, offers more commands for grouping support and + comes with optional [[#extensions][extensions]]. - [[https://github.com/oantolin/icomplete-vertical][Icomplete-vertical]]: This package enhances the Emacs builtin Icomplete with a vertical display. In contrast to Vertico, the candidates are rotated such that the current candidate always appears at the top. From my perspective, diff --git a/extensions/vertico-quick.el b/extensions/vertico-quick.el new file mode 100644 index 0000000..2f07539 --- /dev/null +++ b/extensions/vertico-quick.el @@ -0,0 +1,132 @@ +;;; vertico-quick.el --- Quick keys for Vertico -*- lexical-binding: t -*- + +;; Copyright (C) 2021 Free Software Foundation, Inc. + +;; Author: Daniel Mendler <m...@daniel-mendler.de> +;; Maintainer: Daniel Mendler <m...@daniel-mendler.de> +;; Created: 2021 +;; Version: 0.1 +;; Package-Requires: ((emacs "27.1")) +;; Homepage: https://github.com/minad/vertico + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This package is a Vertico extension, which provides quick keys. +;; (define-key vertico-map "\M-q" #'vertico-quick-insert) +;; (define-key vertico-map "\C-q" #'vertico-quick-exit) + +;;; Code: + +(require 'vertico) + +(defface vertico-quick1 + '((t :weight bold :background "#d5baff" :foreground "black")) + "First quick key." + :group 'vertico + :group 'faces) + +(defface vertico-quick2 + '((t :weight bold :background "#8ae4f2" :foreground "black")) + "Second quick key." + :group 'vertico + :group 'faces) + +(defcustom vertico-quick1 "asdfgh" + "Single level quick keys." + :type 'string + :group 'vertico) + +(defcustom vertico-quick2 "jkl" + "Two level quick keys." + :type 'string + :group 'vertico) + +(defvar-local vertico-quick--index 0) +(defvar-local vertico-quick--list 0) +(defvar-local vertico-quick--first nil) + +(defun vertico-quick--format-candidate (orig cand prefix suffix index) + "Format candidate, see `vertico--format-candidate' for arguments." + (let* ((fst (length vertico-quick1)) + (snd (length vertico-quick2)) + (len (+ fst snd)) + (idx vertico-quick--index)) + (setq vertico-quick--index (1+ idx)) + (funcall orig cand + (concat + (if (>= idx fst) + (let ((first (elt vertico-quick2 (mod (/ (- idx fst) len) snd))) + (second (elt (concat vertico-quick1 vertico-quick2) (mod (- idx fst) len)))) + (push (cons (+ (lsh first 16) second) index) vertico-quick--list) + (cond + ((eq first vertico-quick--first) + (concat " " (propertize (char-to-string second) 'face 'vertico-quick1))) + (vertico-quick--first + " ") + (t + (concat (propertize (char-to-string first) 'face 'vertico-quick1) + (propertize (char-to-string second) 'face 'vertico-quick2))))) + (let ((first (elt vertico-quick1 (mod idx fst)))) + (push (cons first index) vertico-quick--list) + (if vertico-quick--first + " " + (concat (propertize (char-to-string first) 'face 'vertico-quick1) " ")))) + (make-string (max 1 (- (length prefix) 2)) ?\s)) + suffix + index))) + +;;;###autoload +(defun vertico-quick-jump () + "Jump to candidate using quick keys." + (interactive) + (let ((vertico-quick--index 0) + (vertico-quick--list) + (key)) + (unwind-protect + (progn + (advice-add #'vertico--format-candidate :around #'vertico-quick--format-candidate) + (vertico--exhibit) + (setq key (read-key)) + (when (seq-position vertico-quick2 key) + (let ((vertico-quick--first key) + (vertico-quick--index 0) + (vertico-quick--list)) + (vertico--exhibit)) + (setq key (+ (lsh key 16) (read-key))))) + (advice-remove #'vertico--format-candidate #'vertico-quick--format-candidate)) + (if-let (idx (alist-get key vertico-quick--list)) + (setq vertico--index idx) + (message "Invalid key") + nil))) + +;;;###autoload +(defun vertico-quick-exit () + "Exit with candidate using quick keys." + (interactive) + (when (vertico-quick-jump) + (vertico-exit))) + +;;;###autoload +(defun vertico-quick-insert () + "Insert candidate using quick keys." + (interactive) + (when (vertico-quick-jump) + (vertico-insert))) + +(provide 'vertico-quick) +;;; vertico-quick.el ends here