;;; macros.el --- non-primitive commands for keyboard macros.
-;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 86, 87, 92, 94, 95 Free Software Foundation, Inc.
;; Maintainer: FSF
+;; Keywords: abbrev
;; This file is part of GNU Emacs.
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Extension commands for keyboard macros. These permit you to assign
+;; a name to the last-defined keyboard macro, expand and insert the
+;; lisp corresponding to a macro, query the user from within a macro,
+;; or apply a macro to each line in the reason.
;;; Code:
(error "No keyboard macro defined"))
(and (fboundp symbol)
(not (stringp (symbol-function symbol)))
+ (not (vectorp (symbol-function symbol)))
(error "Function %s is already defined and not a keyboard macro."
symbol))
+ (if (string-equal symbol "")
+ (error "No command name given"))
(fset symbol last-kbd-macro))
;;;###autoload
To save a kbd macro, visit a file of Lisp code such as your `~/.emacs',
use this command, and then save the file."
(interactive "CInsert kbd macro (name): \nP")
- (insert "(fset '")
- (prin1 macroname (current-buffer))
- (insert "\n ")
- (let ((beg (point)) end)
- (prin1 (symbol-function macroname) (current-buffer))
- (setq end (point-marker))
- (goto-char beg)
- (while (< (point) end)
- (let ((char (following-char)))
- (cond ((< char 32)
- (delete-region (point) (1+ (point)))
- (insert "\\C-" (+ 96 char)))
- ((< char 127)
- (forward-char 1))
- ((= char 127)
- (delete-region (point) (1+ (point)))
- (insert "\\C-?"))
- ((< char 160)
- (delete-region (point) (1+ (point)))
- (insert "\\M-C-" (- char 32)))
- ((< char 255)
- (delete-region (point) (1+ (point)))
- (insert "\\M-" (- char 128)))
- ((= char 255)
- (delete-region (point) (1+ (point)))
- (insert "\\M-C-?"))))))
- (insert ")\n")
- (if keys
- (let ((keys (where-is-internal macroname nil)))
- (while keys
- (insert "(global-set-key ")
- (prin1 (car keys) (current-buffer))
- (insert " '")
- (prin1 macroname (current-buffer))
- (insert ")\n")
- (setq keys (cdr keys))))))
+ (let (definition)
+ (if (string= (symbol-name macroname) "")
+ (progn
+ (setq macroname 'last-kbd-macro definition last-kbd-macro)
+ (insert "(setq "))
+ (setq definition (symbol-function macroname))
+ (insert "(fset '"))
+ (prin1 macroname (current-buffer))
+ (insert "\n ")
+ (if (stringp definition)
+ (let ((beg (point)) end)
+ (prin1 definition (current-buffer))
+ (setq end (point-marker))
+ (goto-char beg)
+ (while (< (point) end)
+ (let ((char (following-char)))
+ (cond ((= char 0)
+ (delete-region (point) (1+ (point)))
+ (insert "\\C-@"))
+ ((< char 27)
+ (delete-region (point) (1+ (point)))
+ (insert "\\C-" (+ 96 char)))
+ ((= char ?\C-\\)
+ (delete-region (point) (1+ (point)))
+ (insert "\\C-\\\\"))
+ ((< char 32)
+ (delete-region (point) (1+ (point)))
+ (insert "\\C-" (+ 64 char)))
+ ((< char 127)
+ (forward-char 1))
+ ((= char 127)
+ (delete-region (point) (1+ (point)))
+ (insert "\\C-?"))
+ ((= char 128)
+ (delete-region (point) (1+ (point)))
+ (insert "\\M-\\C-@"))
+ ((= char (aref "\M-\C-\\" 0))
+ (delete-region (point) (1+ (point)))
+ (insert "\\M-\\C-\\\\"))
+ ((< char 155)
+ (delete-region (point) (1+ (point)))
+ (insert "\\M-\\C-" (- char 32)))
+ ((< char 160)
+ (delete-region (point) (1+ (point)))
+ (insert "\\M-\\C-" (- char 64)))
+ ((= char (aref "\M-\\" 0))
+ (delete-region (point) (1+ (point)))
+ (insert "\\M-\\\\"))
+ ((< char 255)
+ (delete-region (point) (1+ (point)))
+ (insert "\\M-" (- char 128)))
+ ((= char 255)
+ (delete-region (point) (1+ (point)))
+ (insert "\\M-\\C-?"))))))
+ (if (vectorp definition)
+ (let ((len (length definition)) (i 0) char mods)
+ (while (< i len)
+ (insert (if (zerop i) ?\[ ?\ ))
+ (setq char (aref definition i)
+ i (1+ i))
+ (cond ((not (numberp char))
+ (prin1 char (current-buffer)))
+ (t
+ (insert "?")
+ (setq mods (event-modifiers char)
+ char (event-basic-type char))
+ (while mods
+ (cond ((eq (car mods) 'control)
+ (insert "\\C-"))
+ ((eq (car mods) 'meta)
+ (insert "\\M-"))
+ ((eq (car mods) 'hyper)
+ (insert "\\H-"))
+ ((eq (car mods) 'super)
+ (insert "\\s-"))
+ ((eq (car mods) 'alt)
+ (insert "\\A-"))
+ ((and (eq (car mods) 'shift)
+ (>= char ?a)
+ (<= char ?z))
+ (setq char (upcase char)))
+ ((eq (car mods) 'shift)
+ (insert "\\S-")))
+ (setq mods (cdr mods)))
+ (cond ((= char ?\\)
+ (insert "\\\\"))
+ ((= char 127)
+ (insert "\\C-?"))
+ ((< char 127)
+ (insert char))
+ (t (insert "\\" (format "%o" char)))))))
+ (insert ?\]))
+ (prin1 definition (current-buffer))))
+ (insert ")\n")
+ (if keys
+ (let ((keys (where-is-internal macroname '(keymap))))
+ (while keys
+ (insert "(global-set-key ")
+ (prin1 (car keys) (current-buffer))
+ (insert " '")
+ (prin1 macroname (current-buffer))
+ (insert ")\n")
+ (setq keys (cdr keys)))))))
;;;###autoload
(defun kbd-macro-query (flag)
With prefix argument, enters recursive edit, reading keyboard
commands even within a kbd macro. You can give different commands
each time the macro executes.
- Without prefix argument, reads a character. Your options are:
-Space -- execute the rest of the macro.
-DEL -- skip the rest of the macro; start next repetition.
-C-d -- skip rest of the macro and don't repeat it any more.
-C-r -- enter a recursive edit, then on exit ask again for a character
-C-l -- redisplay screen and ask again."
+ Without prefix argument, asks whether to continue running the macro.
+Your options are: \\<query-replace-map>
+\\[act] Finish this iteration normally and continue with the next.
+\\[skip] Skip the rest of this iteration, and start the next.
+\\[exit] Stop the macro entirely right now.
+\\[recenter] Redisplay the screen, then ask again.
+\\[edit] Enter recursive edit; ask again when you exit from that."
(interactive "P")
- (or executing-macro
+ (or executing-kbd-macro
defining-kbd-macro
(error "Not defining or executing kbd macro"))
(if flag
- (let (executing-macro defining-kbd-macro)
+ (let (executing-kbd-macro defining-kbd-macro)
(recursive-edit))
- (if (not executing-macro)
+ (if (not executing-kbd-macro)
nil
- (let ((loop t))
+ (let ((loop t)
+ (msg (substitute-command-keys
+ "Proceed with macro?\\<query-replace-map>\
+ (\\[act], \\[skip], \\[exit], \\[recenter], \\[edit]) ")))
(while loop
- (let ((char (let ((executing-macro nil)
- (defining-kbd-macro nil))
- (message "Proceed with macro? (Space, DEL, C-d, C-r or C-l) ")
- (read-char))))
- (cond ((= char ? )
+ (let ((key (let ((executing-kbd-macro nil)
+ (defining-kbd-macro nil))
+ (message "%s" msg)
+ (read-event)))
+ def)
+ (setq key (vector key))
+ (setq def (lookup-key query-replace-map key))
+ (cond ((eq def 'act)
(setq loop nil))
- ((= char ?\177)
+ ((eq def 'skip)
(setq loop nil)
- (setq executing-macro ""))
- ((= char ?\C-d)
+ (setq executing-kbd-macro ""))
+ ((eq def 'exit)
(setq loop nil)
- (setq executing-macro t))
- ((= char ?\C-l)
+ (setq executing-kbd-macro t))
+ ((eq def 'recenter)
(recenter nil))
- ((= char ?\C-r)
- (let (executing-macro defining-kbd-macro)
- (recursive-edit))))))))))
+ ((eq def 'edit)
+ (let (executing-kbd-macro defining-kbd-macro)
+ (recursive-edit)))
+ ((eq def 'quit)
+ (setq quit-flag t))
+ (t
+ (or (eq def 'help)
+ (ding))
+ (with-output-to-temp-buffer "*Help*"
+ (princ
+ (substitute-command-keys
+ "Specify how to proceed with keyboard macro execution.
+Possibilities: \\<query-replace-map>
+\\[act] Finish this iteration normally and continue with the next.
+\\[skip] Skip the rest of this iteration, and start the next.
+\\[exit] Stop the macro entirely right now.
+\\[recenter] Redisplay the screen, then ask again.
+\\[edit] Enter recursive edit; ask again when you exit from that."))
+ (save-excursion
+ (set-buffer standard-output)
+ (help-mode)))))))))))
;;;###autoload
(defun apply-macro-to-region-lines (top bottom &optional macro)
(set-marker end-marker nil)
(set-marker next-line-marker nil))))
-;;;###autoload
-(define-key ctl-x-map "q" 'kbd-macro-query)
+;;;###autoload (define-key ctl-x-map "q" 'kbd-macro-query)
+
+(provide 'macros)
;;; macros.el ends here