dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

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