;;; kmacro.el --- enhanced keyboard macros
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Keywords: keyboard convenience
;; 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, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
"Simplified keyboard macro user interface."
:group 'keyboard
:group 'convenience
+ :version "22.1"
:link '(emacs-commentary-link :tag "Commentary" "kmacro.el")
:link '(emacs-library-link :tag "Lisp File" "kmacro.el"))
(global-set-key (vector kmacro-call-mouse-event) 'kmacro-end-call-mouse))
+;;; Called from keyboard-quit
+
+(defun kmacro-keyboard-quit ()
+ (or (not defining-kbd-macro)
+ (eq defining-kbd-macro 'append)
+ (kmacro-ring-empty-p)
+ (kmacro-pop-ring)))
+
;;; Keyboard macro counter
(defvar kmacro-counter 0
"*Current keyboard macro counter.")
+(defvar kmacro-default-counter-format "%d")
+
(defvar kmacro-counter-format "%d"
"*Current keyboard macro counter format.")
"Insert macro counter and increment with ARG or 1 if missing.
With \\[universal-argument], insert previous kmacro-counter (but do not modify counter)."
(interactive "P")
- (setq kmacro-initial-counter-value nil)
+ (if kmacro-initial-counter-value
+ (setq kmacro-counter kmacro-initial-counter-value
+ kmacro-initial-counter-value nil))
(if (and arg (listp arg))
(insert (format kmacro-counter-format kmacro-last-counter))
(insert (format kmacro-counter-format kmacro-counter))
(defun kmacro-set-format (format)
"Set macro counter FORMAT."
- (interactive "sMacro Counter Format (printf format): ")
+ (interactive "sMacro Counter Format: ")
(setq kmacro-counter-format
(if (equal format "") "%d" format))
;; redefine initial macro counter if we are not executing a macro.
(if (not (or defining-kbd-macro executing-kbd-macro))
- (setq kmacro-counter-format-start kmacro-counter-format)))
+ (setq kmacro-default-counter-format kmacro-counter-format)))
(defun kmacro-display-counter (&optional value)
"Set kmacro-counter to ARG or prompt if missing.
With \\[universal-argument] prefix, reset counter to its value prior to this iteration of the macro."
(interactive "NMacro counter value: ")
- (setq kmacro-last-counter kmacro-counter
- kmacro-counter (if (and current-prefix-arg (listp current-prefix-arg))
- kmacro-counter-value-start
- arg))
- ;; setup initial macro counter value if we are not executing a macro.
- (setq kmacro-initial-counter-value
- (and (not (or defining-kbd-macro executing-kbd-macro))
- kmacro-counter))
- (unless executing-kbd-macro
- (kmacro-display-counter)))
+ (if (not (or defining-kbd-macro executing-kbd-macro))
+ (kmacro-display-counter (setq kmacro-initial-counter-value arg))
+ (setq kmacro-last-counter kmacro-counter
+ kmacro-counter (if (and current-prefix-arg (listp current-prefix-arg))
+ kmacro-counter-value-start
+ arg))
+ (unless executing-kbd-macro
+ (kmacro-display-counter))))
(defun kmacro-add-counter (arg)
"Add numeric prefix arg (prompt if missing) to macro counter.
With \\[universal-argument], restore previous counter value."
(interactive "NAdd to macro counter: ")
- (setq kmacro-initial-counter-value nil)
+ (if kmacro-initial-counter-value
+ (setq kmacro-counter kmacro-initial-counter-value
+ kmacro-initial-counter-value nil))
(let ((last kmacro-last-counter))
(setq kmacro-last-counter kmacro-counter
kmacro-counter (if (and current-prefix-arg (listp current-prefix-arg))
(let* ((x 60)
(m (format-kbd-macro macro))
(l (length m))
- (z (and nil trunc (> l x))))
- (message (format "%s: %s%s" (or descr "Macro")
- (if z (substring m 0 (1- x)) m) (if z "..." ""))))
+ (z (and trunc (> l x))))
+ (message "%s%s: %s%s" (or descr "Macro")
+ (if (= kmacro-counter 0) ""
+ (format " [%s]"
+ (format kmacro-counter-format-start kmacro-counter)))
+ (if z (substring m 0 (1- x)) m) (if z "..." "")))
(message (or empty "No keyboard macros defined"))))
kmacro-initial-counter-value nil
kmacro-counter-value-start kmacro-counter
kmacro-last-counter kmacro-counter
- kmacro-counter-format-start kmacro-counter-format))
+ kmacro-counter-format kmacro-default-counter-format
+ kmacro-counter-format-start kmacro-default-counter-format))
(start-kbd-macro append
(and append
(if kmacro-execute-before-append
(> (car arg) 4)
- (= (car arg) 4)))))))
+ (= (car arg) 4))))
+ (if (and defining-kbd-macro append)
+ (setq defining-kbd-macro 'append)))))
;;;###autoload
counting the definition just completed as the first repetition.
An argument of zero means repeat until error."
(interactive "P")
- (end-kbd-macro arg #'kmacro-loop-setup-function)
- (when (and last-kbd-macro (= (length last-kbd-macro) 0))
- (message "Ignore empty macro")
- (kmacro-pop-ring)))
+ ;; Isearch may push the kmacro-end-macro key sequence onto the macro.
+ ;; Just ignore it when executing the macro.
+ (unless executing-kbd-macro
+ (end-kbd-macro arg #'kmacro-loop-setup-function)
+ (when (and last-kbd-macro (= (length last-kbd-macro) 0))
+ (message "Ignore empty macro")
+ (kmacro-pop-ring))))
;;;###autoload
When you call the macro, you can call the macro again by repeating
just the last key in the key sequence that you used to call this
command. See `kmacro-call-repeat-key' and `kmacro-call-repeat-with-arg'
-for details on how to adjust or disable this behaviour.
+for details on how to adjust or disable this behavior.
To make a macro permanent so you can call it even after defining
others, use \\[kmacro-name-last-macro]."
;; letters and digits, provided that we inhibit the keymap while
;; executing the macro later on (but that's controversial...)
+(defun kmacro-lambda-form (mac &optional counter format)
+ "Create lambda form for macro bound to symbol or key."
+ (if counter
+ (setq mac (list mac counter format)))
+ `(lambda (&optional arg)
+ "Keyboard macro."
+ (interactive "p")
+ (kmacro-exec-ring-item ',mac arg)))
+
+(defun kmacro-extract-lambda (mac)
+ "Extract kmacro from a kmacro lambda form."
+ (and (consp mac)
+ (eq (car mac) 'lambda)
+ (setq mac (assoc 'kmacro-exec-ring-item mac))
+ (consp (cdr mac))
+ (consp (car (cdr mac)))
+ (consp (cdr (car (cdr mac))))
+ (setq mac (car (cdr (car (cdr mac)))))
+ (listp mac)
+ (= (length mac) 3)
+ (arrayp (car mac))
+ mac))
+
+
(defun kmacro-bind-to-key (arg)
"When not defining or executing a macro, offer to bind last macro to a key.
The key sequences [C-x C-k 0] through [C-x C-k 9] and [C-x C-k A]
(format-kbd-macro key-seq)
cmd))))
(define-key global-map key-seq
- `(lambda (&optional arg)
- "Keyboard macro."
- (interactive "p")
- (kmacro-exec-ring-item ',(kmacro-ring-head) arg)))
+ (kmacro-lambda-form (kmacro-ring-head)))
(message "Keyboard macro bound to %s" (format-kbd-macro key-seq))))))
symbol))
(if (string-equal symbol "")
(error "No command name given"))
- (fset symbol
- `(lambda (&optional arg)
- "Keyboard macro."
- (interactive "p")
- (kmacro-exec-ring-item ',(kmacro-ring-head) arg)))
+ (fset symbol (kmacro-lambda-form (kmacro-ring-head)))
(put symbol 'kmacro t))
(defun kmacro-step-edit-prompt (macro index)
;; Show step-edit prompt
(let ((keys (and (not kmacro-step-edit-appending)
- index (substring macro index executing-macro-index)))
+ index (substring macro index executing-kbd-macro-index)))
(future (and (not kmacro-step-edit-appending)
- (substring macro executing-macro-index)))
+ (substring macro executing-kbd-macro-index)))
(message-log-max nil)
(curmsg (current-message)))
;; TODO: Scroll macro if max-mini-window-height is too small.
- (message (concat
+ (message "%s"
+ (concat
(format "Macro: %s%s%s%s%s\n"
(format-kbd-macro kmacro-step-edit-new-macro 1)
(if (and kmacro-step-edit-new-macro (> (length kmacro-step-edit-new-macro) 0)) " " "")
(not (eq kmacro-step-edit-action t)))
;; Find the actual end of this key sequence.
;; Must be able to backtrack in case we actually execute it.
- (setq restore-index executing-macro-index)
+ (setq restore-index executing-kbd-macro-index)
(let (unread-command-events)
(quoted-insert 0)
(when unread-command-events
- (setq executing-macro-index (- executing-macro-index (length unread-command-events))
- next-index executing-macro-index)))))
+ (setq executing-kbd-macro-index (- executing-kbd-macro-index (length unread-command-events))
+ next-index executing-kbd-macro-index)))))
;; Query the user; stop macro exection temporarily
(let ((macro executing-kbd-macro)
(when unread-command-events
(setq kmacro-step-edit-new-macro
(substring kmacro-step-edit-new-macro 0 (- (length unread-command-events)))
- executing-macro-index (- executing-macro-index (length unread-command-events)))))
+ executing-kbd-macro-index (- executing-kbd-macro-index (length unread-command-events)))))
(setq current-prefix-arg nil
prefix-arg nil)
(setq act 'ignore))
(setq act t)
t)
((member act '(insert-1 insert))
- (setq executing-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index))
+ (setq executing-kbd-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index))
(setq kmacro-step-edit-inserting (if (eq act 'insert-1) 1 t))
nil)
((member act '(replace-1 replace))
(setq kmacro-step-edit-inserting (if (eq act 'replace-1) 1 t))
(setq kmacro-step-edit-prefix-index nil)
- (if (= executing-macro-index (length executing-kbd-macro))
+ (if (= executing-kbd-macro-index (length executing-kbd-macro))
(setq executing-kbd-macro (vconcat executing-kbd-macro [nil])
kmacro-step-edit-appending t))
nil)
((eq act 'append)
(setq kmacro-step-edit-inserting t)
- (if (= executing-macro-index (length executing-kbd-macro))
+ (if (= executing-kbd-macro-index (length executing-kbd-macro))
(setq executing-kbd-macro (vconcat executing-kbd-macro [nil])
kmacro-step-edit-appending t))
t)
((eq act 'append-end)
- (if (= executing-macro-index (length executing-kbd-macro))
+ (if (= executing-kbd-macro-index (length executing-kbd-macro))
(setq executing-kbd-macro (vconcat executing-kbd-macro [nil])
kmacro-step-edit-inserting t
kmacro-step-edit-appending t)
(setq act t)
t)
((eq act 'help)
- (setq executing-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index))
+ (setq executing-kbd-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index))
(setq kmacro-step-edit-help (not kmacro-step-edit-help))
nil)
(t ;; Ignore unknown responses
- (setq executing-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index))
+ (setq executing-kbd-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index))
nil))
- (if (> executing-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index))
+ (if (> executing-kbd-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index))
(setq kmacro-step-edit-new-macro
(vconcat kmacro-step-edit-new-macro
(substring executing-kbd-macro
(or kmacro-step-edit-prefix-index kmacro-step-edit-key-index)
- (if (eq act t) nil executing-macro-index)))
+ (if (eq act t) nil executing-kbd-macro-index)))
kmacro-step-edit-prefix-index nil))
(if restore-index
- (setq executing-macro-index restore-index)))
+ (setq executing-kbd-macro-index restore-index)))
(t
(setq this-command 'ignore)))
(setq kmacro-step-edit-key-index next-index)))
(executing-kbd-macro nil)
(defining-kbd-macro nil)
cmd keys next-index)
- (setq executing-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index)
+ (setq executing-kbd-macro-index (or kmacro-step-edit-prefix-index kmacro-step-edit-key-index)
kmacro-step-edit-prefix-index nil)
(kmacro-step-edit-prompt macro nil)
;; Now, we have read a key sequence from the macro, but we don't want
(setq kmacro-step-edit-inserting nil)
(when unread-command-events
(setq keys (substring keys 0 (- (length unread-command-events)))
- executing-macro-index (- executing-macro-index (length unread-command-events))
- next-index executing-macro-index
+ executing-kbd-macro-index (- executing-kbd-macro-index (length unread-command-events))
+ next-index executing-kbd-macro-index
unread-command-events nil)))
(setq cmd 'ignore)
nil)
((eq kmacro-step-edit-active 'ignore)
(setq this-command 'ignore))
((eq kmacro-step-edit-active 'append-end)
- (if (= executing-macro-index (length executing-kbd-macro))
+ (if (= executing-kbd-macro-index (length executing-kbd-macro))
(setq executing-kbd-macro (vconcat executing-kbd-macro [nil])
kmacro-step-edit-inserting t
kmacro-step-edit-appending t
(when kmacro-step-edit-active
(add-hook 'pre-command-hook 'kmacro-step-edit-pre-command nil nil)
(if kmacro-step-edit-key-index
- (setq executing-macro-index kmacro-step-edit-key-index)
- (setq kmacro-step-edit-key-index executing-macro-index))))
+ (setq executing-kbd-macro-index kmacro-step-edit-key-index)
+ (setq kmacro-step-edit-key-index executing-kbd-macro-index))))
(defun kmacro-step-edit-macro ()