config

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

consult-kmacro.el (3519B)


      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 (eval-when-compile (require 'subr-x))
     31 
     32 (defvar consult-kmacro--history nil)
     33 
     34 (defun consult-kmacro--candidates ()
     35   "Return alist of kmacros and indices."
     36   (thread-last
     37     ;; List of macros
     38     (append (and last-kbd-macro (list (kmacro-ring-head))) kmacro-ring)
     39     ;; Emacs 29 uses OClosures.  I like OClosures but it would have been better
     40     ;; if public APIs wouldn't change like that.
     41     (mapcar (lambda (x)
     42               (static-if (> emacs-major-version 28)
     43                   (list (kmacro--keys x) (kmacro--counter x) (kmacro--format x) x)
     44                 `(,@x ,x))))
     45     ;; Filter mouse clicks
     46     (seq-remove (lambda (x) (seq-some #'mouse-event-p (car x))))
     47     ;; Format macros
     48     (mapcar (pcase-lambda (`(,keys ,counter ,format ,km))
     49               (propertize
     50                (format-kbd-macro keys 1)
     51                'consult--candidate km
     52                'consult-kmacro--annotation
     53                ;; If the counter is 0 and the counter format is its default,
     54                ;; then there is a good chance that the counter isn't actually
     55                ;; being used.  This can only be wrong when a user
     56                ;; intentionally starts the counter with a negative value and
     57                ;; then increments it to 0.
     58                (cond
     59                 ((not (equal format "%d")) ;; show counter for non-default format
     60                  (format " (counter=%d, format=%s) " counter format))
     61                 ((/= counter 0) ;; show counter if non-zero
     62                  (format " (counter=%d)" counter))))))
     63     (delete-dups)))
     64 
     65 ;;;###autoload
     66 (defun consult-kmacro (arg)
     67   "Run a chosen keyboard macro.
     68 
     69 With prefix ARG, run the macro that many times.
     70 Macros containing mouse clicks are omitted."
     71   (interactive "p")
     72   (let ((km (consult--read
     73              (or (consult-kmacro--candidates)
     74                  (user-error "No keyboard macros defined"))
     75              :prompt "Keyboard macro: "
     76              :category 'consult-kmacro
     77              :require-match t
     78              :sort nil
     79              :history 'consult-kmacro--history
     80              :annotate
     81              (lambda (cand)
     82                (get-text-property 0 'consult-kmacro--annotation cand))
     83              :lookup #'consult--lookup-candidate)))
     84     ;; Kmacros are lambdas (oclosures) on Emacs 29
     85     (funcall (static-if (> emacs-major-version 28)
     86                  km
     87                (kmacro-lambda-form km))
     88              arg)))
     89 
     90 (provide 'consult-kmacro)
     91 ;;; consult-kmacro.el ends here