diff options
| author | Craig Jennings <c@cjennings.net> | 2025-09-06 23:03:27 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2025-09-06 23:03:27 -0500 |
| commit | 4904553ae7d809286ed8993b17e37d3ec34e75d9 (patch) | |
| tree | c07f7554f861842fe9e0145412ac920293de5e5b | |
| parent | 5cd5a9cadf5624be581d40df6e41fc32a8220c84 (diff) | |
| download | dotemacs-4904553ae7d809286ed8993b17e37d3ec34e75d9.tar.gz dotemacs-4904553ae7d809286ed8993b17e37d3ec34e75d9.zip | |
refactor(keyboard-macros): Improve structure and error handling
Reorganized the module to improve code structure and readability:
- Removed duplicate definition of ensure-macros-file
- Added explicit file creation before saving macros
- Added proper error handling when loading macros file
- Added function to save unnamed macros on exit
- Grouped keybindings together
- Cleaned up documentation formatting
| -rw-r--r-- | modules/keyboard-macros.el | 69 |
1 files changed, 29 insertions, 40 deletions
diff --git a/modules/keyboard-macros.el b/modules/keyboard-macros.el index cff25b39..a7605cfd 100644 --- a/modules/keyboard-macros.el +++ b/modules/keyboard-macros.el @@ -8,21 +8,20 @@ ;; All commands are built on top of the built-in =kmacro= machinery, but ;; add a lightweight workflow and persistence across sessions. ;; -;; User Workflow: +;; Workflow: ;; ;; 1. Start recording with C-F3 (or M-x cj/kbd-macro-start-or-end) ;; This toggles macro recording on. ;; Now you can perform all the edits you want recorded in the macro. ;; ;; 2. Stop recording with C-F3 (or M-x cj/kbd-macro-start-or-end) -;; This stops recording and the macro becomes the “last keyboard macro.” +;; This stops recording and the macro becomes the "last keyboard macro." ;; ;; 3. Replay your macro <f3> (or M-x call-last-kbd-macro) ;; ;; 4. Name your macro with M-<F3> ;; You will be prompted for a short name (e.g. =align-comments=, -;; =cleanup-trail-spaces=). This name is how you’ll refer to it later. -;; +;; =cleanup-trail-spaces=). This name is how you'll refer to it later. ;; ;; 5. Recall that macro later with M-x [the name you gave the macro] ;; @@ -36,7 +35,7 @@ (require 'user-constants) ;; definition of sync-dir constant is here. -(defvar macros-file (concat sync-dir "macros.el") +(defvar macros-file (concat sync-dir "macros.el") "The location of the macros file for recorded saved macros via M-f3.") (defun ensure-macros-file (file) @@ -45,22 +44,18 @@ (with-temp-file file (insert ";;; -*- lexical-binding: t -*-\n")))) -(when (file-exists-p macros-file) - (load macros-file)) - (defun cj/kbd-macro-start-or-end () "Toggle start/end of keyboard macro definition." (interactive) (if defining-kbd-macro (end-kbd-macro) (start-kbd-macro nil))) -(global-set-key (kbd "C-<f3>") #'cj/kbd-macro-start-or-end) -(global-set-key (kbd "<f3>") #'call-last-kbd-macro) (defun cj/save-maybe-edit-macro (name) "Save last macro as NAME in `macros-file'; edit if prefix arg." (interactive "SName of macro: ") (kmacro-name-last-macro name) + (ensure-macros-file macros-file) (find-file macros-file) (goto-char (point-max)) (newline) @@ -72,40 +67,34 @@ (find-file macros-file) (goto-char (point-max))) name) + +(defun cj/open-macros-file () + "Open the keyboard macros file." + (interactive) + (ensure-macros-file macros-file) + (find-file macros-file)) + +;; Set up key bindings +(global-set-key (kbd "C-<f3>") #'cj/kbd-macro-start-or-end) +(global-set-key (kbd "<f3>") #'call-last-kbd-macro) (global-set-key (kbd "M-<f3>") #'cj/save-maybe-edit-macro) +(global-set-key (kbd "s-<f3>") #'cj/open-macros-file) -(global-set-key (kbd "s-<f3>") (lambda () (interactive) (find-file macros-file))) +;; Add hook to save any unnamed macros on exit if desired +(defun cj/save-last-kbd-macro-on-exit () + "Save the last keyboard macro before exiting Emacs if it's not saved." + (when (and last-kbd-macro (not (kmacro-name-last-macro))) + (when (y-or-n-p "Save last keyboard macro before exiting? ") + (call-interactively #'cj/save-maybe-edit-macro)))) -(defun ensure-macros-file (file) - "Ensure FILE exists and its first line enables lexical-binding." - (unless (file-exists-p file) - (with-temp-file file - (insert ";;; -*- lexical-binding: t -*-\n")))) +(add-hook 'kill-emacs-hook #'cj/save-last-kbd-macro-on-exit) +;; Load existing macros file with proper error handling (when (file-exists-p macros-file) - (load macros-file)) + (condition-case err + (load macros-file) + (error + (message "Error loading keyboard macros file: %s" (error-message-string err))))) (provide 'keyboard-macros) -;;; keyboard-macros.el ends here. - - -;; --------------------------------- ERT Tests --------------------------------- -;; Run these tests with M-x ert RET t RET - -(require 'ert) - -(ert-deftest keyboard-macros/ensure-macros-file-creates-header () - "ensure-macros-file creates FILE with the right header." - (let ((file (make-temp-file "macros-test" nil ".el"))) - (unwind-protect - (progn - (delete-file file) - (should-not (file-exists-p file)) - (ensure-macros-file file) - (should (file-exists-p file)) - (let ((contents (with-temp-buffer - (insert-file-contents file) - (buffer-string)))) - (should (string= contents ";;; -*- lexical-binding: t -*-\n")))) - (when (file-exists-p file) - (delete-file file))))) +;;; keyboard-macros.el ends here |
