;;; kmacro.el --- enhanced keyboard macros
-;; Copyright (C) 2002-2011 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2013 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Keywords: keyboard convenience
;; naming and binding
(define-key map "b" 'kmacro-bind-to-key)
(define-key map "n" 'kmacro-name-last-macro)
+ (define-key map "x" 'kmacro-to-register)
map)
"Keymap for keyboard macro commands.")
(defalias 'kmacro-keymap kmacro-keymap)
;;; Keyboard macro counter
(defvar kmacro-counter 0
- "*Current keyboard macro counter.")
+ "Current keyboard macro counter.")
(defvar kmacro-default-counter-format "%d")
(defvar kmacro-counter-format "%d"
- "*Current keyboard macro counter format.")
+ "Current keyboard macro counter format.")
(defvar kmacro-counter-format-start kmacro-counter-format
"Macro format at start of macro execution.")
;;;###autoload
-(defun kmacro-call-macro (arg &optional no-repeat end-macro)
- "Call the last keyboard macro that you defined with \\[kmacro-start-macro].
+(defun kmacro-call-macro (arg &optional no-repeat end-macro macro)
+ "Call the keyboard MACRO that you defined with \\[kmacro-start-macro].
A prefix argument serves as a repeat count. Zero means repeat until error.
+MACRO defaults to `last-kbd-macro'.
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
To make a macro permanent so you can call it even after defining
others, use \\[kmacro-name-last-macro]."
(interactive "p")
- (let ((repeat-key (and (null no-repeat)
- (> (length (this-single-command-keys)) 1)
- last-input-event))
- repeat-key-str)
+ (let ((repeat-key (and (or (and (null no-repeat)
+ (> (length (this-single-command-keys)) 1))
+ ;; Used when we're in the process of repeating.
+ (eq no-repeat 'repeating))
+ last-input-event)))
(if end-macro
- (kmacro-end-macro arg)
- (call-last-kbd-macro arg #'kmacro-loop-setup-function))
+ (kmacro-end-macro arg) ; modifies last-kbd-macro
+ (let ((last-kbd-macro (or macro last-kbd-macro)))
+ (call-last-kbd-macro arg #'kmacro-loop-setup-function)))
(when (consp arg)
(setq arg (car arg)))
(when (and (or (null arg) (> arg 0))
(if (eq kmacro-call-repeat-key t)
repeat-key
kmacro-call-repeat-key)))
- (setq repeat-key-str (format-kbd-macro (vector repeat-key) nil))
- (while repeat-key
- ;; Issue a hint to the user, if the echo area isn't in use.
- (unless (current-message)
- (message "(Type %s to repeat macro%s)"
- repeat-key-str
- (if (and kmacro-call-repeat-with-arg
- arg (> arg 1))
- (format " %d times" arg) "")))
- (if (equal repeat-key (read-event))
- (progn
- (clear-this-command-keys t)
- (call-last-kbd-macro (and kmacro-call-repeat-with-arg arg)
- #'kmacro-loop-setup-function)
- (setq last-input-event nil))
- (setq repeat-key nil)))
- (when last-input-event
- (clear-this-command-keys t)
- (setq unread-command-events (list last-input-event))))))
+ ;; Issue a hint to the user, if the echo area isn't in use.
+ (unless (current-message)
+ (message "(Type %s to repeat macro%s)"
+ (format-kbd-macro (vector repeat-key) nil)
+ (if (and kmacro-call-repeat-with-arg
+ arg (> arg 1))
+ (format " %d times" arg) "")))
+ ;; Can't use the `keep-pred' arg because this overlay keymap needs to be
+ ;; removed during the next run of the kmacro (i.e. we need to add&remove
+ ;; this overlay-map at each repetition).
+ (set-temporary-overlay-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (vector repeat-key)
+ `(lambda () (interactive)
+ (kmacro-call-macro ,(and kmacro-call-repeat-with-arg arg)
+ 'repeating nil ,(if end-macro
+ last-kbd-macro
+ (or macro last-kbd-macro)))))
+ map)))))
;;; Combined function key bindings:
;; Create a separate keymap installed as a minor-mode keymap (e.g. in
;; the emulation-mode-map-alists) in which macro bindings are made
;; independent of any other bindings. When first binding is made,
-;; the kemap is created, installed, and enabled. Key seq. C-x C-k +
+;; the keymap is created, installed, and enabled. Key seq. C-x C-k +
;; can then be used to toggle the use of this keymap on and off.
;; This means that it would be safe(r) to bind ordinary keys like
;; letters and digits, provided that we inhibit the keymap while
(put symbol 'kmacro t))
+(defun kmacro-execute-from-register (k)
+ (kmacro-call-macro current-prefix-arg nil nil k))
+
+(defun kmacro-to-register (r)
+ "Store the last keyboard macro in register R."
+ (interactive
+ (progn
+ (or last-kbd-macro (error "No keyboard macro defined"))
+ (list (read-char "Save to register: "))))
+ (set-register r (registerv-make
+ last-kbd-macro
+ :jump-func 'kmacro-execute-from-register
+ :print-func (lambda (k)
+ (princ (format "a keyboard macro:\n %s"
+ (format-kbd-macro k))))
+ :insert-func (lambda (k)
+ (insert (format-kbd-macro k))))))
+
+
(defun kmacro-view-macro (&optional _arg)
"Display the last keyboard macro.
If repeated, it shows previous elements in the macro ring."
(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
+ ;; Query the user; stop macro execution temporarily.
(let ((macro executing-kbd-macro)
(executing-kbd-macro nil)
(defining-kbd-macro nil))
(setq cmd 'ignore)
nil)
((memq cmd kmacro-step-edit-prefix-commands)
- (setq universal-argument-num-events 0)
(reset-this-command-lengths)
nil)
((eq cmd 'universal-argument-other-key)
(setq kmacro-step-edit-action t)
- (setq universal-argument-num-events 0)
(reset-this-command-lengths)
(if (numberp kmacro-step-edit-inserting)
(setq kmacro-step-edit-inserting nil))
(setq kmacro-step-edit-prefix-index nil)
(reset-this-command-lengths)
(setq overriding-terminal-local-map nil)
- (setq universal-argument-num-events nil)
(setq next-index kmacro-step-edit-key-index)
t)
(t nil))