From b43609693f5ac4cf98a13e59eb80a7cac4659202 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Tue, 28 Dec 2021 19:40:03 -0600 Subject: Add +kmacro.el --- init.el | 6 +++++ lisp/+kmacro.el | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 lisp/+kmacro.el diff --git a/init.el b/init.el index 961e90a..196792b 100644 --- a/init.el +++ b/init.el @@ -288,6 +288,12 @@ (ibuffer-auto-mode +1) (ibuffer-switch-to-saved-filter-groups "default")))) +(setup kmacro + (:also-load +kmacro) + (with-eval-after-load '+kmacro + (+kmacro-recording-indicator-mode +1) + (+kmacro-block-undo-mode +1))) + (setup magit ;; This setup is weird because of dependency issues (:straight (transient :host github :repo "magit/transient" :branch "master") diff --git a/lisp/+kmacro.el b/lisp/+kmacro.el new file mode 100644 index 0000000..2b2916f --- /dev/null +++ b/lisp/+kmacro.el @@ -0,0 +1,69 @@ +;;; +kmacro.el -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Many of these come from this Reddit thread: +;; https://old.reddit.com/r/emacs/comments/rlli0u/whats_your_favorite_defadvice/ + +;;; Code: + +(require 'kmacro) + +;; Indicate when a kmacro is being recorded in the mode-line + +(defface +kmacro-modeline nil + "Face when kmacro is active") + +(set-face-attribute '+kmacro-modeline nil + :background "Firebrick" + :box '(:line-width -1 :color "salmon" + :style released-button)) + +(defun +kmacro-change-mode-line (&rest _) + "Remap the mode-line face when recording a kmacro." + (add-to-list 'face-remapping-alist '(mode-line . +kmacro-modeline))) + +(defun +kmacro-restore-mode-line (&rest _) + "Restore the mode-line face after kmacro is done recording." + (setf face-remapping-alist + (assoc-delete-all 'mode-line face-remapping-alist))) + +(define-minor-mode +kmacro-recording-indicator-mode + "Change the mode-line's face when recording a kmacro." + :lighter "" + :global t + (if +kmacro-recording-indicator-mode + (progn + (advice-add #'kmacro-start-macro :before #'+kmacro-change-mode-line) + (advice-add #'kmacro-keyboard-quit :after #'+kmacro-restore-mode-line) + (advice-add #'kmacro-end-macro :after #'+kmacro-restore-mode-line)) + (+kmacro-restore-mode-line) + (advice-remove #'kmacro-start-macro #'+kmacro-change-mode-line) + (advice-remove #'kmacro-keyboard-quit #'+kmacro-restore-mode-line) + (advice-remove #'kmacro-end-macro #'+kmacro-restore-mode-line))) + +;; Undo keyboard macros in a single bound (like vi!) + +(defun +kmacro-block-undo (fn &rest args) + (let ((marker (prepare-change-group))) + (unwind-protect (apply fn args) + (undo-amalgamate-change-group marker)))) + +(define-minor-mode +kmacro-block-undo-mode + "Undo kmacros all at once (like vi)." + :global t + :lighter " KUndo" + (if +kmacro-block-undo-mode + (dolist (fn '(kmacro-call-macro + kmacro-exec-ring-item + dot-mode-execute + apply-macro-to-region-lines)) + (advice-add fn :around #'+kmacro-block-undo)) + (dolist (fn '(kmacro-call-macro + kmacro-exec-ring-item + dot-mode-execute + apply-macro-to-region-lines)) + (advice-remove fn #'+kmacro-block-undo)))) + +(provide '+kmacro) +;;; +kmacro.el ends here -- cgit 1.4.1-21-gabe81