diff options
-rw-r--r-- | init.el | 6 | ||||
-rw-r--r-- | lisp/+kmacro.el | 69 |
2 files changed, 75 insertions, 0 deletions
diff --git a/init.el b/init.el index 961e90a..196792b 100644 --- a/init.el +++ b/init.el | |||
@@ -288,6 +288,12 @@ | |||
288 | (ibuffer-auto-mode +1) | 288 | (ibuffer-auto-mode +1) |
289 | (ibuffer-switch-to-saved-filter-groups "default")))) | 289 | (ibuffer-switch-to-saved-filter-groups "default")))) |
290 | 290 | ||
291 | (setup kmacro | ||
292 | (:also-load +kmacro) | ||
293 | (with-eval-after-load '+kmacro | ||
294 | (+kmacro-recording-indicator-mode +1) | ||
295 | (+kmacro-block-undo-mode +1))) | ||
296 | |||
291 | (setup magit | 297 | (setup magit |
292 | ;; This setup is weird because of dependency issues | 298 | ;; This setup is weird because of dependency issues |
293 | (:straight (transient :host github :repo "magit/transient" :branch "master") | 299 | (: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 @@ | |||
1 | ;;; +kmacro.el -*- lexical-binding: t; -*- | ||
2 | |||
3 | ;;; Commentary: | ||
4 | |||
5 | ;; Many of these come from this Reddit thread: | ||
6 | ;; https://old.reddit.com/r/emacs/comments/rlli0u/whats_your_favorite_defadvice/ | ||
7 | |||
8 | ;;; Code: | ||
9 | |||
10 | (require 'kmacro) | ||
11 | |||
12 | ;; Indicate when a kmacro is being recorded in the mode-line | ||
13 | |||
14 | (defface +kmacro-modeline nil | ||
15 | "Face when kmacro is active") | ||
16 | |||
17 | (set-face-attribute '+kmacro-modeline nil | ||
18 | :background "Firebrick" | ||
19 | :box '(:line-width -1 :color "salmon" | ||
20 | :style released-button)) | ||
21 | |||
22 | (defun +kmacro-change-mode-line (&rest _) | ||
23 | "Remap the mode-line face when recording a kmacro." | ||
24 | (add-to-list 'face-remapping-alist '(mode-line . +kmacro-modeline))) | ||
25 | |||
26 | (defun +kmacro-restore-mode-line (&rest _) | ||
27 | "Restore the mode-line face after kmacro is done recording." | ||
28 | (setf face-remapping-alist | ||
29 | (assoc-delete-all 'mode-line face-remapping-alist))) | ||
30 | |||
31 | (define-minor-mode +kmacro-recording-indicator-mode | ||
32 | "Change the mode-line's face when recording a kmacro." | ||
33 | :lighter "" | ||
34 | :global t | ||
35 | (if +kmacro-recording-indicator-mode | ||
36 | (progn | ||
37 | (advice-add #'kmacro-start-macro :before #'+kmacro-change-mode-line) | ||
38 | (advice-add #'kmacro-keyboard-quit :after #'+kmacro-restore-mode-line) | ||
39 | (advice-add #'kmacro-end-macro :after #'+kmacro-restore-mode-line)) | ||
40 | (+kmacro-restore-mode-line) | ||
41 | (advice-remove #'kmacro-start-macro #'+kmacro-change-mode-line) | ||
42 | (advice-remove #'kmacro-keyboard-quit #'+kmacro-restore-mode-line) | ||
43 | (advice-remove #'kmacro-end-macro #'+kmacro-restore-mode-line))) | ||
44 | |||
45 | ;; Undo keyboard macros in a single bound (like vi!) | ||
46 | |||
47 | (defun +kmacro-block-undo (fn &rest args) | ||
48 | (let ((marker (prepare-change-group))) | ||
49 | (unwind-protect (apply fn args) | ||
50 | (undo-amalgamate-change-group marker)))) | ||
51 | |||
52 | (define-minor-mode +kmacro-block-undo-mode | ||
53 | "Undo kmacros all at once (like vi)." | ||
54 | :global t | ||
55 | :lighter " KUndo" | ||
56 | (if +kmacro-block-undo-mode | ||
57 | (dolist (fn '(kmacro-call-macro | ||
58 | kmacro-exec-ring-item | ||
59 | dot-mode-execute | ||
60 | apply-macro-to-region-lines)) | ||
61 | (advice-add fn :around #'+kmacro-block-undo)) | ||
62 | (dolist (fn '(kmacro-call-macro | ||
63 | kmacro-exec-ring-item | ||
64 | dot-mode-execute | ||
65 | apply-macro-to-region-lines)) | ||
66 | (advice-remove fn #'+kmacro-block-undo)))) | ||
67 | |||
68 | (provide '+kmacro) | ||
69 | ;;; +kmacro.el ends here | ||