consult-kmacro.el (3507B)
1 ;;; consult-kmacro.el --- Provides the command `consult-kmacro' -*- lexical-binding: t -*- 2 3 ;; Copyright (C) 2021-2024 Free Software Foundation, Inc. 4 5 ;; This file is part of GNU Emacs. 6 7 ;; This program is free software: you can redistribute it and/or modify 8 ;; it under the terms of the GNU General Public License as published by 9 ;; the Free Software Foundation, either version 3 of the License, or 10 ;; (at your option) any later version. 11 12 ;; This program is distributed in the hope that it will be useful, 13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 ;; GNU General Public License for more details. 16 17 ;; You should have received a copy of the GNU General Public License 18 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 19 20 ;;; Commentary: 21 22 ;; Provides the command `consult-kmacro'. This is an extra package, 23 ;; to allow lazy loading of kmacro.el. The `consult-kmacro' command 24 ;; is autoloaded. 25 26 ;;; Code: 27 28 (require 'consult) 29 (require 'kmacro) 30 31 (defvar consult-kmacro--history nil) 32 33 (defun consult-kmacro--candidates () 34 "Return alist of kmacros and indices." 35 (thread-last 36 ;; List of macros 37 (append (and last-kbd-macro (list (kmacro-ring-head))) kmacro-ring) 38 ;; Emacs 29 uses OClosures. I like OClosures but it would have been better 39 ;; if public APIs wouldn't change like that. 40 (mapcar (lambda (x) 41 (if (eval-when-compile (> emacs-major-version 28)) 42 (list (kmacro--keys x) (kmacro--counter x) (kmacro--format x) x) 43 `(,@x ,x)))) 44 ;; Filter mouse clicks 45 (seq-remove (lambda (x) (seq-some #'mouse-event-p (car x)))) 46 ;; Format macros 47 (mapcar (pcase-lambda (`(,keys ,counter ,format ,km)) 48 (propertize 49 (format-kbd-macro keys 1) 50 'consult--candidate km 51 'consult-kmacro--annotation 52 ;; If the counter is 0 and the counter format is its default, 53 ;; then there is a good chance that the counter isn't actually 54 ;; being used. This can only be wrong when a user 55 ;; intentionally starts the counter with a negative value and 56 ;; then increments it to 0. 57 (cond 58 ((not (equal format "%d")) ;; show counter for non-default format 59 (format " (counter=%d, format=%s) " counter format)) 60 ((/= counter 0) ;; show counter if non-zero 61 (format " (counter=%d)" counter)))))) 62 (delete-dups))) 63 64 ;;;###autoload 65 (defun consult-kmacro (arg) 66 "Run a chosen keyboard macro. 67 68 With prefix ARG, run the macro that many times. 69 Macros containing mouse clicks are omitted." 70 (interactive "p") 71 (let ((km (consult--read 72 (or (consult-kmacro--candidates) 73 (user-error "No keyboard macros defined")) 74 :prompt "Keyboard macro: " 75 :category 'consult-kmacro 76 :require-match t 77 :sort nil 78 :history 'consult-kmacro--history 79 :annotate 80 (lambda (cand) 81 (get-text-property 0 'consult-kmacro--annotation cand)) 82 :lookup #'consult--lookup-candidate))) 83 ;; Kmacros are lambdas (oclosures) on Emacs 29 84 (funcall (if (eval-when-compile (> emacs-major-version 28)) 85 km 86 (kmacro-lambda-form km)) 87 arg))) 88 89 (provide 'consult-kmacro) 90 ;;; consult-kmacro.el ends here