aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/emacs/kmacro.texi19
-rw-r--r--etc/NEWS14
-rw-r--r--lisp/edmacro.el113
3 files changed, 134 insertions, 12 deletions
diff --git a/doc/emacs/kmacro.texi b/doc/emacs/kmacro.texi
index fc1402b489d..05095bc68b8 100644
--- a/doc/emacs/kmacro.texi
+++ b/doc/emacs/kmacro.texi
@@ -515,6 +515,19 @@ editing it. Type @kbd{C-h m} once in that buffer to display details
515of how to edit the macro. When you are finished editing, type 515of how to edit the macro. When you are finished editing, type
516@kbd{C-c C-c}. 516@kbd{C-c C-c}.
517 517
518@findex edmacro-insert-key
519@findex edmacro-set-macro-to-region-lines
520 @code{edmacro-mode}, the major mode used by
521@code{kmacro-edit-macro}, provides commands for more easily editing
522the formatted macro. Use @kbd{C-c C-q} (@code{edmacro-insert-key}) to
523insert the next key sequence that you type into the buffer using the
524correct format, similar to @kbd{C-q} (@code{quoted-insert}). Use
525@kbd{C-c C-r} (@code{edmacro-set-macro-to-region-lines}) to replace
526the macro's text with the text in the region. If the region does not
527begin at the start of a line or if it does not end at the end of a
528line, the region is extended to include complete lines. If the region
529ends at the beginning of a line, that final line is excluded.
530
518@findex edit-kbd-macro 531@findex edit-kbd-macro
519@kindex C-x C-k e 532@kindex C-x C-k e
520 You can edit a named keyboard macro or a macro bound to a key by typing 533 You can edit a named keyboard macro or a macro bound to a key by typing
@@ -523,9 +536,13 @@ keyboard input that you would use to invoke the macro---@kbd{C-x e} or
523@kbd{M-x @var{name}} or some other key sequence. 536@kbd{M-x @var{name}} or some other key sequence.
524 537
525@findex kmacro-edit-lossage 538@findex kmacro-edit-lossage
539@vindex edmacro-reverse-macro-lines
526@kindex C-x C-k l 540@kindex C-x C-k l
527 You can edit the last 300 keystrokes as a macro by typing 541 You can edit the last 300 keystrokes as a macro by typing
528@kbd{C-x C-k l} (@code{kmacro-edit-lossage}). 542@kbd{C-x C-k l} (@code{kmacro-edit-lossage}). By default,
543your most recent keystrokes are listed at the bottom of the buffer.
544To list a macro's key sequences in reverse order, set
545@code{edmacro-reverse-macro-lines} to @code{t}.
529 546
530@node Keyboard Macro Step-Edit 547@node Keyboard Macro Step-Edit
531@section Stepwise Editing a Keyboard Macro 548@section Stepwise Editing a Keyboard Macro
diff --git a/etc/NEWS b/etc/NEWS
index c146f464585..4e7ad25b484 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -772,6 +772,20 @@ neither of which have been supported by Emacs since version 23.1.
772The user option 'url-gateway-nslookup-program' and the function 772The user option 'url-gateway-nslookup-program' and the function
773'url-gateway-nslookup-host' are consequently also obsolete. 773'url-gateway-nslookup-host' are consequently also obsolete.
774 774
775+++
776** Edmacro
777
778*** New command 'edmacro-set-macro-to-region-lines'.
779Bound to 'C-c C-r', this command replaces the macro text with the
780lines of the region. If needed, the region is extended to include
781whole lines. If the region ends at the beginning of a line, that last
782line is excluded.
783
784*** New user option 'edmacro-reverse-macro-lines'.
785When this is non-nil, the lines of key sequences are displayed with
786the most recent line fist. This is can be useful when working with
787macros with many lines, such as from 'kmacro-edit-lossage'.
788
775 789
776* New Modes and Packages in Emacs 30.1 790* New Modes and Packages in Emacs 30.1
777 791
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
index bbf5a7f0495..6cad8158321 100644
--- a/lisp/edmacro.el
+++ b/lisp/edmacro.el
@@ -73,9 +73,19 @@ Default nil means to write characters above \\177 in octal notation."
73 :type 'boolean 73 :type 'boolean
74 :group 'kmacro) 74 :group 'kmacro)
75 75
76(defcustom edmacro-reverse-macro-lines nil
77 "Non-nil if `edit-kbd-macro' should show the most recent line of key sequences first.
78
79This is useful when dealing with long lists of key sequences, such as
80from `kmacro-edit-lossage'."
81 :type 'boolean
82 :group 'kmacro
83 :version "30.1")
84
76(defvar-keymap edmacro-mode-map 85(defvar-keymap edmacro-mode-map
77 "C-c C-c" #'edmacro-finish-edit 86 "C-c C-c" #'edmacro-finish-edit
78 "C-c C-q" #'edmacro-insert-key) 87 "C-c C-q" #'edmacro-insert-key
88 "C-c C-r" #'edmacro-set-macro-to-region-lines)
79 89
80(defface edmacro-label 90(defface edmacro-label
81 '((default :inherit bold) 91 '((default :inherit bold)
@@ -88,7 +98,10 @@ Default nil means to write characters above \\177 in octal notation."
88 :group 'kmacro) 98 :group 'kmacro)
89 99
90(defvar edmacro-mode-font-lock-keywords 100(defvar edmacro-mode-font-lock-keywords
91 `((,(rx bol (group (or "Command" "Key" "Macro") ":")) 0 'edmacro-label) 101 `((,(rx bol (group (or "Command" "Key"
102 (seq "Macro" (zero-or-one " (most recent line first)")))
103 ":"))
104 0 'edmacro-label)
92 (,(rx bol 105 (,(rx bol
93 (group ";; Keyboard Macro Editor. Press ") 106 (group ";; Keyboard Macro Editor. Press ")
94 (group (*? nonl)) 107 (group (*? nonl))
@@ -166,7 +179,13 @@ With a prefix argument, format the macro in a more concise way."
166 (let* ((oldbuf (current-buffer)) 179 (let* ((oldbuf (current-buffer))
167 (mmac (edmacro-fix-menu-commands mac)) 180 (mmac (edmacro-fix-menu-commands mac))
168 (fmt (edmacro-format-keys mmac 1)) 181 (fmt (edmacro-format-keys mmac 1))
169 (fmtv (edmacro-format-keys mmac (not prefix))) 182 (fmtv (let ((fmtv (edmacro-format-keys mmac (not prefix))))
183 (if (not edmacro-reverse-macro-lines)
184 fmtv
185 (with-temp-buffer
186 (insert fmtv)
187 (reverse-region (point-min) (point-max))
188 (buffer-string)))))
170 (buf (get-buffer-create "*Edit Macro*"))) 189 (buf (get-buffer-create "*Edit Macro*")))
171 (message "Formatting keyboard macro...done") 190 (message "Formatting keyboard macro...done")
172 (switch-to-buffer buf) 191 (switch-to-buffer buf)
@@ -181,6 +200,9 @@ With a prefix argument, format the macro in a more concise way."
181 (setq-local font-lock-defaults 200 (setq-local font-lock-defaults
182 '(edmacro-mode-font-lock-keywords nil nil ((?\" . "w")))) 201 '(edmacro-mode-font-lock-keywords nil nil ((?\" . "w"))))
183 (setq font-lock-multiline nil) 202 (setq font-lock-multiline nil)
203 ;; Make buffer-local so that the commands still work
204 ;; even if the default value changes.
205 (make-local-variable 'edmacro-reverse-macro-lines)
184 (erase-buffer) 206 (erase-buffer)
185 (insert (substitute-command-keys 207 (insert (substitute-command-keys
186 (concat 208 (concat
@@ -202,7 +224,9 @@ With a prefix argument, format the macro in a more concise way."
202 (insert "Key: none\n"))) 224 (insert "Key: none\n")))
203 (when (and mac-counter mac-format) 225 (when (and mac-counter mac-format)
204 (insert (format "Counter: %d\nFormat: \"%s\"\n" mac-counter mac-format)))) 226 (insert (format "Counter: %d\nFormat: \"%s\"\n" mac-counter mac-format))))
205 (insert "\nMacro:\n\n") 227 (insert (format "\nMacro%s:\n\n" (if edmacro-reverse-macro-lines
228 " (most recent line first)"
229 "")))
206 (save-excursion 230 (save-excursion
207 (insert fmtv "\n")) 231 (insert fmtv "\n"))
208 (recenter '(4)) 232 (recenter '(4))
@@ -255,6 +279,33 @@ or nil, use a compact 80-column format."
255 279
256;;; Commands for *Edit Macro* buffer. 280;;; Commands for *Edit Macro* buffer.
257 281
282(defvar edmacro--skip-line-regexp
283 "[ \t]*\\($\\|;;\\|REM[ \t\n]\\)"
284 "A regexp identifying lines that should be ignored.")
285
286(defvar edmacro--command-line-regexp
287 "Command:[ \t]*\\([^ \t\n]*\\)[ \t]*$"
288 "A regexp identifying the line containing the command name.")
289
290(defvar edmacro--key-line-regexp
291 "Key:\\(.*\\)$"
292 "A regexp identifying the line containing the bound key sequence.")
293
294(defvar edmacro--counter-line-regexp
295 "Counter:[ \t]*\\([^ \t\n]*\\)[ \t]*$"
296 "A regexp identifying the line containing the counter value.")
297
298(defvar edmacro--format-line-regexp
299 "Format:[ \t]*\"\\([^\n]*\\)\"[ \t]*$"
300 "A regexp identifying the line containing the counter format.")
301
302(defvar edmacro--macro-lines-regexp
303 (rx "Macro"
304 (zero-or-one " (most recent line first)")
305 ":"
306 (zero-or-more (any " \t\n")))
307 "A regexp identifying the lines that precede the macro's contents.")
308
258(defun edmacro-finish-edit () 309(defun edmacro-finish-edit ()
259 (interactive nil edmacro-mode) 310 (interactive nil edmacro-mode)
260 (unless (eq major-mode 'edmacro-mode) 311 (unless (eq major-mode 'edmacro-mode)
@@ -266,9 +317,9 @@ or nil, use a compact 80-column format."
266 (top (point-min))) 317 (top (point-min)))
267 (goto-char top) 318 (goto-char top)
268 (let ((case-fold-search nil)) 319 (let ((case-fold-search nil))
269 (while (cond ((looking-at "[ \t]*\\($\\|;;\\|REM[ \t\n]\\)") 320 (while (cond ((looking-at edmacro--skip-line-regexp)
270 t) 321 t)
271 ((looking-at "Command:[ \t]*\\([^ \t\n]*\\)[ \t]*$") 322 ((looking-at edmacro--command-line-regexp)
272 (when edmacro-store-hook 323 (when edmacro-store-hook
273 (error "\"Command\" line not allowed in this context")) 324 (error "\"Command\" line not allowed in this context"))
274 (let ((str (match-string 1))) 325 (let ((str (match-string 1)))
@@ -283,7 +334,7 @@ or nil, use a compact 80-column format."
283 cmd))) 334 cmd)))
284 (keyboard-quit)))) 335 (keyboard-quit))))
285 t) 336 t)
286 ((looking-at "Key:\\(.*\\)$") 337 ((looking-at edmacro--key-line-regexp)
287 (when edmacro-store-hook 338 (when edmacro-store-hook
288 (error "\"Key\" line not allowed in this context")) 339 (error "\"Key\" line not allowed in this context"))
289 (let ((key (kbd (match-string 1)))) 340 (let ((key (kbd (match-string 1))))
@@ -303,21 +354,21 @@ or nil, use a compact 80-column format."
303 (edmacro-format-keys key 1)))) 354 (edmacro-format-keys key 1))))
304 (keyboard-quit)))))) 355 (keyboard-quit))))))
305 t) 356 t)
306 ((looking-at "Counter:[ \t]*\\([^ \t\n]*\\)[ \t]*$") 357 ((looking-at edmacro--counter-line-regexp)
307 (when edmacro-store-hook 358 (when edmacro-store-hook
308 (error "\"Counter\" line not allowed in this context")) 359 (error "\"Counter\" line not allowed in this context"))
309 (let ((str (match-string 1))) 360 (let ((str (match-string 1)))
310 (unless (equal str "") 361 (unless (equal str "")
311 (setq mac-counter (string-to-number str)))) 362 (setq mac-counter (string-to-number str))))
312 t) 363 t)
313 ((looking-at "Format:[ \t]*\"\\([^\n]*\\)\"[ \t]*$") 364 ((looking-at edmacro--format-line-regexp)
314 (when edmacro-store-hook 365 (when edmacro-store-hook
315 (error "\"Format\" line not allowed in this context")) 366 (error "\"Format\" line not allowed in this context"))
316 (let ((str (match-string 1))) 367 (let ((str (match-string 1)))
317 (unless (equal str "") 368 (unless (equal str "")
318 (setq mac-format str))) 369 (setq mac-format str)))
319 t) 370 t)
320 ((looking-at "Macro:[ \t\n]*") 371 ((looking-at edmacro--macro-lines-regexp)
321 (goto-char (match-end 0)) 372 (goto-char (match-end 0))
322 nil) 373 nil)
323 ((eobp) nil) 374 ((eobp) nil)
@@ -336,7 +387,13 @@ or nil, use a compact 80-column format."
336 (when (buffer-name obuf) 387 (when (buffer-name obuf)
337 (set-buffer obuf)) 388 (set-buffer obuf))
338 (message "Compiling keyboard macro...") 389 (message "Compiling keyboard macro...")
339 (let ((mac (edmacro-parse-keys str))) 390 (let ((mac (edmacro-parse-keys (if edmacro-reverse-macro-lines
391 (with-temp-buffer
392 (insert str)
393 (reverse-region (point-min)
394 (point-max))
395 (buffer-string))
396 str))))
340 (message "Compiling keyboard macro...done") 397 (message "Compiling keyboard macro...done")
341 (if store-hook 398 (if store-hook
342 (funcall store-hook mac) 399 (funcall store-hook mac)
@@ -372,6 +429,36 @@ or nil, use a compact 80-column format."
372 (insert (edmacro-format-keys key t) "\n") 429 (insert (edmacro-format-keys key t) "\n")
373 (insert (edmacro-format-keys key) " "))) 430 (insert (edmacro-format-keys key) " ")))
374 431
432(defun edmacro-set-macro-to-region-lines (beg end)
433 "Set the macro text to lines of text in the buffer between BEG and END.
434
435Interactively, BEG and END are the beginning and end of the
436region. If the region does not begin at the start of a line or
437if it does not end at the end of a line, the region is extended
438to include complete lines. If the region ends at the beginning
439of a line, that final line is excluded."
440 (interactive "*r" edmacro-mode)
441 ;; Use `save-excursion' to restore region if there are any errors.
442 ;; If there are no errors, update the macro text, then go to the
443 ;; beginning of the macro text.
444 (let ((final-position))
445 (save-excursion
446 (goto-char beg)
447 (unless (bolp) (setq beg (pos-bol)))
448 (goto-char end)
449 (unless (or (bolp) (eolp)) (setq end (pos-eol)))
450 (let ((text (buffer-substring beg end)))
451 (goto-char (point-min))
452 (if (not (let ((case-fold-search nil))
453 (re-search-forward edmacro--macro-lines-regexp nil t)))
454 (user-error "\"Macro:\" line not found")
455 (delete-region (match-end 0)
456 (point-max))
457 (goto-char (point-max))
458 (insert text)
459 (setq final-position (match-beginning 0)))))
460 (goto-char final-position)))
461
375(defun edmacro-mode () 462(defun edmacro-mode ()
376 "\\<edmacro-mode-map>Keyboard Macro Editing mode. Press \ 463 "\\<edmacro-mode-map>Keyboard Macro Editing mode. Press \
377\\[edmacro-finish-edit] to save and exit. 464\\[edmacro-finish-edit] to save and exit.
@@ -393,6 +480,10 @@ or \"none\" for no key bindings.
393You can edit these lines to change the places where the new macro 480You can edit these lines to change the places where the new macro
394is stored. 481is stored.
395 482
483Press \\[edmacro-set-macro-to-region-lines] to replace the text following the \"Macro:\" line
484with the text of the lines overlapping the region of text between
485point and mark. If that region ends at the beginning of a line,
486that final line is excluded.
396 487
397Format of keyboard macros during editing: 488Format of keyboard macros during editing:
398 489