emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/ivy-hydra be231a5 001/395: counsel.el (counsel-kmacro):


From: Basil L. Contovounesios
Subject: [elpa] externals/ivy-hydra be231a5 001/395: counsel.el (counsel-kmacro): Add
Date: Thu, 25 Feb 2021 08:31:18 -0500 (EST)

branch: externals/ivy-hydra
commit be231a50c6e9561df1bde4e5c68ca199e9a92c49
Author: dude <ej32u@protonmail.com>
Commit: Oleh Krehel <ohwoeowho@gmail.com>

    counsel.el (counsel-kmacro): Add
    
    - Main function ‘counsel-kmacro’.
    - Formatting function ‘counsel--kmacro-format-function’.
    - Separator variable ‘counsel-kmacro-separator’.
    - Ivy actions for deleting macros and copying the counter’s format or value.
    - Ivy action to execute an existing macro a given number of times with
      a specified format and starting value.
    
    Fixes #2280
---
 counsel.el | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 150 insertions(+)

diff --git a/counsel.el b/counsel.el
index 3ee1533..5192200 100644
--- a/counsel.el
+++ b/counsel.el
@@ -5052,6 +5052,156 @@ You can insert or kill the name of the selected font."
             :action #'insert
             :caller 'counsel-fonts))
 
+;;** `counsel-kmacro'
+(defvar counsel-kmacro-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "C-k") #'counsel-kmacro-kill)
+    map))
+
+(defun counsel-kmacro-kill ()
+  "Kill the line, or delete the keyboard macro."
+  (interactive)
+  (if (not (eolp))
+      (ivy-kill-line)
+    (counsel-kmacro-action-delete-kmacro
+     (assoc
+      (ivy-state-current ivy-last)
+      (ivy-state-collection ivy-last)))
+    (ivy--kill-current-candidate)))
+
+;;;###autoload
+(defun counsel-kmacro ()
+  "Interactively choose and run a keyboard macro.
+
+With prefix argument, run macro that many times.
+
+Macros are run using the current value of `kmacro-counter-value-start' their 
defined format.
+One can use actions to copy the counter format or initial counter value of a 
command,
+using them for the next defined macro."
+  (interactive)
+  (if (and (eq last-kbd-macro nil) (eq kmacro-ring nil))
+      (message "counsel-kmacro: No keyboard macros defined.")
+    (ivy-read
+     (concat "Execute macro (counter at "
+             (number-to-string (or kmacro-initial-counter-value 
kmacro-counter))
+             "): ")
+     (counsel--kmacro-candidates)
+     :keymap counsel-kmacro-map
+     :require-match t
+     :action #'counsel-kmacro-action-run
+     :caller 'counsel-kmacro)))
+
+(ivy-configure 'counsel-kmacro
+  :format-fn #'counsel--kmacro-format-function)
+
+(defvar counsel-kmacro-separator "\n------------------------\n"
+  "Separator used between macros in the list.")
+
+(defun counsel--kmacro-format-function (formatted-kmacro)
+  "Transform CAND-PAIRS into a string for `counsel-kmacro'."
+  (ivy--format-function-generic
+   (lambda (str) (ivy--add-face str 'ivy-current-match))
+   (lambda (str) str)
+   formatted-kmacro
+   (propertize counsel-kmacro-separator 'face 'ivy-separator)))
+
+(defun counsel--kmacro-candidates ()
+  "Create the list of keyboard macros used by `counsel-kmacro'.
+This is a combination of `kmacro-ring' and `last-kbd-macro',
+`kmacro-counter-format-start', and `kmacro-counter-value-start'."
+  (mapcar
+   (lambda (kmacro)
+     (cons
+      (concat "(" (nth 2 kmacro) "," (number-to-string (nth 1 kmacro)) "): "
+              (format-kbd-macro (if (listp kmacro) (car kmacro) kmacro) 1))
+      kmacro))
+   (cons
+    (if (listp last-kbd-macro)
+        last-kbd-macro
+      (list
+       last-kbd-macro
+       kmacro-counter-value-start
+       kmacro-counter-format-start))
+    kmacro-ring)))
+
+(defun counsel-kmacro-action-run (x)
+  "Run keyboard macro."
+  (let* ((actual-kmacro (cdr x))
+         (kmacro-keys (nth 0 actual-kmacro))
+         (kmacro-counter-format-start (nth 2 actual-kmacro)))
+    ;; With prefix argument, call the macro that many times.
+    (kmacro-call-macro (or current-prefix-arg 1) t nil kmacro-keys)))
+
+(defun counsel-kmacro-action-delete-kmacro (x)
+  "Delete a keyboard macro within `counsel-kmacro'.
+
+Either remove a macro from `kmacro-ring', or pop the head of the
+`kmacro-ring' and set `last-kbd-macro' to that value."
+  (let ((actual-macro (cdr x)))
+    (if (eq (nth 0 actual-macro) last-kbd-macro)
+        (setq last-kbd-macro
+              (if (eq kmacro-ring nil)
+                  nil
+                (let ((prev-macro (pop kmacro-ring)))
+                  (if (listp prev-macro)
+                      (nth 0 prev-macro)
+                    prev-macro))))
+      (setq kmacro-ring (remove actual-macro kmacro-ring)))))
+
+(defun counsel-kmacro-action-copy-counter (x)
+  "Set `kmacro-counter' a value used by an existing macro."
+  (let* ((actual-kmacro (cdr x))
+         (number (nth 1 actual-kmacro)))
+    (kmacro-set-counter number)))
+
+(defun counsel-kmacro-action-copy-format (x)
+  "Copy the format of the chosen macro for the next defined macro."
+  (let* ((actual-kmacro (cdr x))
+         (format (nth 2 actual-kmacro)))
+    (kmacro-set-format format)))
+
+(defun counsel-kmacro-action-execute-after-prompt (x)
+  "Execute an existing keyboard macro, prompting for a starting counter value, 
a
+counter format, and the number of times to execute the macro.
+
+If called with a prefix, will suggest those values."
+  (let* ((default-string (if current-prefix-arg
+                             (number-to-string current-prefix-arg)
+                           nil))
+         (actual-kmacro (cdr x))
+         (kmacro-keys (nth 0 actual-kmacro))
+         (kmacro-starting-counter (number-to-string (nth 1 actual-kmacro)))
+         (kmacro-starting-format (nth 2 actual-kmacro))
+         (number-of-iterations
+          (read-from-minibuffer
+           (concat "Enter number of iterations for macro (default: "
+                   (or default-string (number-to-string 2))
+                   "): ")
+           nil nil t nil
+           (or default-string (number-to-string 2))))
+         (kmacro-initial-counter-value
+          (read-from-minibuffer
+           (concat "Enter a starting counter for macro (default: "
+                   (or default-string kmacro-starting-counter)
+                   "): ")
+           nil nil t nil
+           (or default-string kmacro-starting-counter)))
+         (kmacro-counter-format-start
+          (symbol-name (read-from-minibuffer
+                        (concat "Enter format for macro counter (default: "
+                                kmacro-starting-format
+                                "): ")
+                        nil nil t nil
+                        kmacro-starting-format))))
+    (kmacro-call-macro number-of-iterations t nil kmacro-keys)))
+
+(ivy-set-actions
+ 'counsel-kmacro
+ '(("c" counsel-kmacro-action-copy-counter "copy counter")
+   ("d" counsel-kmacro-action-delete-kmacro "delete")
+   ("f" counsel-kmacro-action-copy-format "copy format")
+   ("e" counsel-kmacro-action-execute-after-prompt "execute after prompt")))
+
 ;;* Misc. OS
 ;;** `counsel-rhythmbox'
 (declare-function dbus-call-method "dbus")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]