HideIfDef mode bug fixes and enhancements. This is #2 of 3 patches based
[bpt/emacs.git] / lisp / kmacro.el
index facc359..4d93926 100644 (file)
@@ -1,7 +1,6 @@
 ;;; kmacro.el --- enhanced keyboard macros
 
-;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 2002-2014 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Keywords: keyboard convenience
@@ -203,6 +202,7 @@ macro to be executed before appending to it."
     ;; 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)
@@ -232,12 +232,12 @@ macro to be executed before appending to it."
 ;;; 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.")
@@ -445,7 +445,8 @@ Optional arg EMPTY is message to print if no macros are defined."
 
 ;;;###autoload
 (defun kmacro-exec-ring-item (item arg)
-  "Execute item ITEM from the macro ring."
+  "Execute item ITEM from the macro ring.
+ARG is the number of times to execute the item."
   ;; Use counter and format specific to the macro on the ring!
   (let ((kmacro-counter (nth 1 item))
        (kmacro-counter-format-start (nth 2 item)))
@@ -480,9 +481,10 @@ without repeating the prefix."
     (kmacro-display (car (car kmacro-ring)) "2nd macro")))
 
 
-(defun kmacro-cycle-ring-next (&optional arg)
+(defun kmacro-cycle-ring-next (&optional _arg)
   "Move to next keyboard macro in keyboard macro ring.
-Displays the selected macro in the echo area."
+Displays the selected macro in the echo area.
+The ARG parameter is unused."
   (interactive)
   (unless (kmacro-ring-empty-p)
     (kmacro-push-ring)
@@ -499,9 +501,10 @@ Displays the selected macro in the echo area."
 (put 'kmacro-cycle-ring-next 'kmacro-repeat 'ring)
 
 
-(defun kmacro-cycle-ring-previous (&optional arg)
+(defun kmacro-cycle-ring-previous (&optional _arg)
   "Move to previous keyboard macro in keyboard macro ring.
-Displays the selected macro in the echo area."
+Displays the selected macro in the echo area.
+The ARG parameter is unused."
   (interactive)
   (unless (kmacro-ring-empty-p)
     (let ((keys (kmacro-get-repeat-prefix))
@@ -527,8 +530,9 @@ Displays the selected macro in the echo area."
     (kmacro-display last-kbd-macro t)))
 
 
-(defun kmacro-delete-ring-head (&optional arg)
-  "Delete current macro from keyboard macro ring."
+(defun kmacro-delete-ring-head (&optional _arg)
+  "Delete current macro from keyboard macro ring.
+The ARG parameter is unused."
   (interactive)
   (unless (kmacro-ring-empty-p t)
     (if (null kmacro-ring)
@@ -614,9 +618,10 @@ An argument of zero means repeat until error."
 
 
 ;;;###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
@@ -626,13 +631,15 @@ 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]."
   (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))
@@ -640,23 +647,25 @@ others, use \\[kmacro-name-last-macro]."
                     (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
+                (format-kbd-macro (vector repeat-key) nil)
                 (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))))))
+                    (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 must add and remove this map at each repetition).
+      (set-transient-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:
@@ -746,7 +755,7 @@ If kbd macro currently being defined end it before activating it."
 ;; 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
@@ -776,7 +785,7 @@ If kbd macro currently being defined end it before activating it."
        mac))
 
 
-(defun kmacro-bind-to-key (arg)
+(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]
 through [C-x C-k Z] are reserved for user bindings, and to bind to
@@ -787,7 +796,8 @@ You can bind to any valid key sequence, but if you try to bind to
 a key with an existing command binding, you will be asked for
 confirmation whether to replace that binding.  Note that the
 binding is made in the `global-map' keymap, so the macro binding
-may be shaded by a local key binding."
+may be shaded by a local key binding.
+The ARG parameter is unused."
   (interactive "p")
   (if (or defining-kbd-macro executing-kbd-macro)
       (if defining-kbd-macro
@@ -836,9 +846,31 @@ Such a \"function\" cannot be called from Lisp, but it is a valid editor command
   (put symbol 'kmacro t))
 
 
-(defun kmacro-view-macro (&optional arg)
+(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.
+
+Interactively, reads the register using `register-read-with-preview'."
+  (interactive
+   (progn
+     (or last-kbd-macro (error "No keyboard macro defined"))
+     (list (register-read-with-preview "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."
+If repeated, it shows previous elements in the macro ring.
+The ARG parameter is unused."
   (interactive)
   (cond
    ((or (kmacro-ring-empty-p)
@@ -915,34 +947,35 @@ without repeating the prefix."
 (defvar kmacro-step-edit-help)          ;; kmacro step edit help enabled
 (defvar kmacro-step-edit-num-input-keys) ;; to ignore duplicate pre-command hook
 
-(defvar kmacro-step-edit-map (make-sparse-keymap)
+(defvar kmacro-step-edit-map
+  (let ((map (make-sparse-keymap)))
+    ;; query-replace-map answers include: `act', `skip', `act-and-show',
+    ;; `exit', `act-and-exit', `edit', `delete-and-edit', `recenter',
+    ;; `automatic', `backup', `exit-prefix', and `help'.")
+    ;; Also: `quit', `edit-replacement'
+
+    (set-keymap-parent map query-replace-map)
+
+    (define-key map "\t" 'act-repeat)
+    (define-key map [tab] 'act-repeat)
+    (define-key map "\C-k" 'skip-rest)
+    (define-key map "c" 'automatic)
+    (define-key map "f" 'skip-keep)
+    (define-key map "q" 'quit)
+    (define-key map "d" 'skip)
+    (define-key map "\C-d" 'skip)
+    (define-key map "i" 'insert)
+    (define-key map "I" 'insert-1)
+    (define-key map "r" 'replace)
+    (define-key map "R" 'replace-1)
+    (define-key map "a" 'append)
+    (define-key map "A" 'append-end)
+    map)
   "Keymap that defines the responses to questions in `kmacro-step-edit-macro'.
 This keymap is an extension to the `query-replace-map', allowing the
 following additional answers: `insert', `insert-1', `replace', `replace-1',
 `append', `append-end', `act-repeat', `skip-end', `skip-keep'.")
 
-;; query-replace-map answers include: `act', `skip', `act-and-show',
-;; `exit', `act-and-exit', `edit', `delete-and-edit', `recenter',
-;; `automatic', `backup', `exit-prefix', and `help'.")
-;; Also: `quit', `edit-replacement'
-
-(set-keymap-parent kmacro-step-edit-map query-replace-map)
-
-(define-key kmacro-step-edit-map "\t" 'act-repeat)
-(define-key kmacro-step-edit-map [tab] 'act-repeat)
-(define-key kmacro-step-edit-map "\C-k" 'skip-rest)
-(define-key kmacro-step-edit-map "c" 'automatic)
-(define-key kmacro-step-edit-map "f" 'skip-keep)
-(define-key kmacro-step-edit-map "q" 'quit)
-(define-key kmacro-step-edit-map "d" 'skip)
-(define-key kmacro-step-edit-map "\C-d" 'skip)
-(define-key kmacro-step-edit-map "i" 'insert)
-(define-key kmacro-step-edit-map "I" 'insert-1)
-(define-key kmacro-step-edit-map "r" 'replace)
-(define-key kmacro-step-edit-map "R" 'replace-1)
-(define-key kmacro-step-edit-map "a" 'append)
-(define-key kmacro-step-edit-map "A" 'append-end)
-
 (defvar kmacro-step-edit-prefix-commands
   '(universal-argument universal-argument-more universal-argument-minus
                       digit-argument negative-argument)
@@ -1018,7 +1051,7 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
          (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))
@@ -1169,12 +1202,10 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
          (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))
@@ -1189,7 +1220,6 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
          (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))
@@ -1268,5 +1298,4 @@ To customize possible responses, change the \"bindings\" in `kmacro-step-edit-ma
 
 (provide 'kmacro)
 
-;; arch-tag: d3fe0b24-ae41-47de-a4d6-41a77d5559f0
 ;;; kmacro.el ends here