mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-27 08:43:40 -07:00
(kmacro-keymap): Group related bindings in
initialization for clarity. Bind C-s to start macro. Remove C-r binding. (kmacro-initial-counter-value): New defvar to hold initial counter value in case we set the value before defining a macro. (kmacro-insert-counter): Clear kmacro-initial-counter-value.. (kmacro-set-counter): Set kmacro-initial-counter-value if we are not defining or executing macro. Doc fix. (kmacro-add-counter): Clear kmacro-initial-counter-value. (kmacro-view-last-item, kmacro-view-item-no): New defvars used to temporarily view older elements on the macro ring without cycling the ring. (kmacro-display): Doc fix. (kmacro-exec-ring-item): New helper function. (kmacro-call-ring-2nd): Use it. (kmacro-call-ring-2nd-repeat): Doc fix. (kmacro-start-macro): Use (and clear) kmacro-initial-counter-value. (kmacro-end-or-call-macro): Execute last viewed macro (using kmacro-exec-ring-item) from ring if this follows kmacro-view-macro. This allows us to find a macro on the ring with C-x C-k C-v C-v ... and execute it (with C-k) without cycling the ring to bring it to the head of the ring. (kmacro-bind-to-key): Doc fix (describe reserved bindings). Allow binding to reserved keys without specifying C-x C-k prefix. Ask for confirmation if entered key sequence is already bound to a non-macro command. (kmacro-view-macro): Repeating command will show older elements on the macro ring; C-k will execute the last viewed macro. (kmacro-view-macro-repeat): Doc fix. Change its kmacro-repeat property from 'ring to 'head.
This commit is contained in:
parent
100df2143b
commit
a1839f0622
1 changed files with 138 additions and 37 deletions
175
lisp/kmacro.el
175
lisp/kmacro.el
|
|
@ -174,29 +174,37 @@ macro to be executed before appending to it."
|
|||
|
||||
(defvar kmacro-keymap
|
||||
(let ((map (make-sparse-keymap)))
|
||||
;; Start, end, execute macros
|
||||
(define-key map "s" 'kmacro-start-macro)
|
||||
(define-key map "\C-s" 'kmacro-start-macro)
|
||||
(define-key map "\C-k" 'kmacro-end-or-call-macro-repeat)
|
||||
(define-key map "\C-e" 'kmacro-edit-macro-repeat)
|
||||
(define-key map "\r" 'kmacro-edit-macro)
|
||||
(define-key map " " 'kmacro-step-edit-macro)
|
||||
(define-key map "l" 'kmacro-edit-lossage)
|
||||
(define-key map "\C-i" 'kmacro-insert-counter)
|
||||
(define-key map "\C-a" 'kmacro-add-counter)
|
||||
(define-key map "\C-v" 'kmacro-view-macro-repeat)
|
||||
(define-key map "\C-l" 'kmacro-call-ring-2nd-repeat)
|
||||
(define-key map "\C-r" 'kmacro-view-ring-2nd)
|
||||
(define-key map "r" 'apply-macro-to-region-lines)
|
||||
(define-key map "q" 'kbd-macro-query) ;; Like C-x q
|
||||
|
||||
;; macro ring
|
||||
(define-key map "\C-n" 'kmacro-cycle-ring-next)
|
||||
(define-key map "\C-p" 'kmacro-cycle-ring-previous)
|
||||
(define-key map "\C-v" 'kmacro-view-macro-repeat)
|
||||
(define-key map "\C-d" 'kmacro-delete-ring-head)
|
||||
(define-key map "\C-t" 'kmacro-swap-ring)
|
||||
(define-key map "\C-l" 'kmacro-call-ring-2nd-repeat)
|
||||
|
||||
;; macro counter
|
||||
(define-key map "\C-f" 'kmacro-set-format)
|
||||
(define-key map "\C-c" 'kmacro-set-counter)
|
||||
(define-key map "\C-t" 'kmacro-swap-ring)
|
||||
(define-key map "b" 'kmacro-bind-to-key)
|
||||
(define-key map "\C-d" 'kmacro-delete-ring-head)
|
||||
;; Compatibility bindings
|
||||
(define-key map "q" 'kbd-macro-query)
|
||||
(define-key map "n" 'name-last-kbd-macro)
|
||||
(define-key map "\C-i" 'kmacro-insert-counter)
|
||||
(define-key map "\C-a" 'kmacro-add-counter)
|
||||
|
||||
;; macro editing
|
||||
(define-key map "\C-e" 'kmacro-edit-macro-repeat)
|
||||
(define-key map "\r" 'kmacro-edit-macro)
|
||||
(define-key map "e" 'edit-kbd-macro)
|
||||
(define-key map "r" 'apply-macro-to-region-lines)
|
||||
(define-key map "l" 'kmacro-edit-lossage)
|
||||
(define-key map " " 'kmacro-step-edit-macro)
|
||||
|
||||
;; naming and binding
|
||||
(define-key map "b" 'kmacro-bind-to-key)
|
||||
(define-key map "n" 'name-last-kbd-macro)
|
||||
map)
|
||||
"Keymap for keyboard macro commands.")
|
||||
(defalias 'kmacro-keymap kmacro-keymap)
|
||||
|
|
@ -229,13 +237,18 @@ macro to be executed before appending to it."
|
|||
(defvar kmacro-counter-value-start kmacro-counter
|
||||
"Macro counter at start of macro execution.")
|
||||
|
||||
(defvar kmacro-last-counter 0 "Last counter inserted by key macro.")
|
||||
(defvar kmacro-last-counter 0
|
||||
"Last counter inserted by key macro.")
|
||||
|
||||
(defvar kmacro-initial-counter-value nil
|
||||
"Initial counter value for the next keyboard macro to be defined.")
|
||||
|
||||
|
||||
(defun kmacro-insert-counter (arg)
|
||||
"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 (and arg (listp arg))
|
||||
(insert (format kmacro-counter-format kmacro-last-counter))
|
||||
(insert (format kmacro-counter-format kmacro-counter))
|
||||
|
|
@ -260,12 +273,16 @@ With \\[universal-argument], insert previous kmacro-counter (but do not modify c
|
|||
|
||||
(defun kmacro-set-counter (arg)
|
||||
"Set kmacro-counter to ARG or prompt if missing.
|
||||
With \\[universal-argument], reset counter to its value prior to this iteration of the macro."
|
||||
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)))
|
||||
|
||||
|
|
@ -274,6 +291,7 @@ With \\[universal-argument], reset counter to its value prior to this iteration
|
|||
"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)
|
||||
(let ((last kmacro-last-counter))
|
||||
(setq kmacro-last-counter kmacro-counter
|
||||
kmacro-counter (if (and current-prefix-arg (listp current-prefix-arg))
|
||||
|
|
@ -303,6 +321,11 @@ the macro ring (when defining or executing) is not stored in the ring;
|
|||
instead it is available in the variables `last-kbd-macro', `kmacro-counter',
|
||||
and `kmacro-counter-format'.")
|
||||
|
||||
;; Remember what we are currently looking at with kmacro-view-macro.
|
||||
|
||||
(defvar kmacro-view-last-item nil)
|
||||
(defvar kmacro-view-item-no 0)
|
||||
|
||||
|
||||
(defun kmacro-ring-head ()
|
||||
"Return pseudo head element in macro ring."
|
||||
|
|
@ -361,8 +384,11 @@ Check only `last-kbd-macro' if optional arg NONE is non-nil."
|
|||
(t nil)))
|
||||
|
||||
|
||||
(defun kmacro-display (macro &optional trunc descr empty )
|
||||
"Display a keyboard MACRO."
|
||||
(defun kmacro-display (macro &optional trunc descr empty)
|
||||
"Display a keyboard MACRO.
|
||||
Optional arg TRUNC non-nil specifies to limit width of macro to 60 chars.
|
||||
Optional arg DESCR is descriptive text for macro; default is \"Macro:\".
|
||||
Optional arg EMPTY is message to print if no macros are defined."
|
||||
(if macro
|
||||
(let* ((x 60)
|
||||
(m (format-kbd-macro macro))
|
||||
|
|
@ -410,19 +436,26 @@ Check only `last-kbd-macro' if optional arg NONE is non-nil."
|
|||
keys)))
|
||||
|
||||
|
||||
(defun kmacro-exec-ring-item (item arg)
|
||||
"Execute item ITEM from the macro ring."
|
||||
;; Use counter and format specific to the macro on the ring!
|
||||
(let ((kmacro-counter (nth 1 item))
|
||||
(kmacro-counter-format-start (nth 2 item)))
|
||||
(execute-kbd-macro (car item) arg #'kmacro-loop-setup-function)
|
||||
(setcar (cdr item) kmacro-counter)))
|
||||
|
||||
|
||||
(defun kmacro-call-ring-2nd (arg)
|
||||
"Execute second keyboard macro at in macro ring."
|
||||
(interactive "P")
|
||||
(unless (kmacro-ring-empty-p)
|
||||
;; should use counter format specific to the macro on the ring!
|
||||
(let ((kmacro-counter (nth 1 (car kmacro-ring)))
|
||||
(kmacro-counter-format-start (nth 2 (car kmacro-ring))))
|
||||
(execute-kbd-macro (car (car kmacro-ring)) arg #'kmacro-loop-setup-function)
|
||||
(setcar (cdr (car kmacro-ring)) kmacro-counter))))
|
||||
(kmacro-exec-ring-item (car kmacro-ring) arg)))
|
||||
|
||||
|
||||
(defun kmacro-call-ring-2nd-repeat (arg)
|
||||
"Like `kmacro-call-ring-2nd', but allow repeat without repeating prefix."
|
||||
"Execute second keyboard macro at in macro ring.
|
||||
This is like `kmacro-call-ring-2nd', but allows repeating macro commands
|
||||
without repeating the prefix."
|
||||
(interactive "P")
|
||||
(let ((keys (kmacro-get-repeat-prefix)))
|
||||
(kmacro-call-ring-2nd arg)
|
||||
|
|
@ -439,7 +472,6 @@ Check only `last-kbd-macro' if optional arg NONE is non-nil."
|
|||
(kmacro-display (car (car kmacro-ring)) "2nd macro")))
|
||||
|
||||
|
||||
|
||||
(defun kmacro-cycle-ring-next (&optional arg)
|
||||
"Move to next keyboard macro in keyboard macro ring.
|
||||
Displays the selected macro in the echo area."
|
||||
|
|
@ -533,7 +565,10 @@ The format of the counter can be modified via \\[kmacro-set-format]."
|
|||
kmacro-ring))
|
||||
(if (>= len kmacro-ring-max)
|
||||
(setcdr (nthcdr len kmacro-ring) nil))))
|
||||
(setq kmacro-counter (if arg (prefix-numeric-value arg) 0)
|
||||
(setq kmacro-counter (or (if arg (prefix-numeric-value arg))
|
||||
kmacro-initial-counter-value
|
||||
0)
|
||||
kmacro-initial-counter-value nil
|
||||
kmacro-counter-value-start kmacro-counter
|
||||
kmacro-last-counter kmacro-counter
|
||||
kmacro-counter-format-start kmacro-counter-format))
|
||||
|
|
@ -645,6 +680,9 @@ With \\[universal-argument], call second macro in macro ring."
|
|||
(if kmacro-call-repeat-key
|
||||
(kmacro-call-macro arg no-repeat t)
|
||||
(kmacro-end-macro arg)))
|
||||
((and (eq this-command 'kmacro-view-macro) ;; We are in repeat mode!
|
||||
kmacro-view-last-item)
|
||||
(kmacro-exec-ring-item (car kmacro-view-last-item) arg))
|
||||
((and arg (listp arg))
|
||||
(kmacro-call-ring-2nd 1))
|
||||
(t
|
||||
|
|
@ -689,34 +727,97 @@ If kbd macro currently being defined end it before activating it."
|
|||
|
||||
;;; Misc. commands
|
||||
|
||||
;; An idea for macro 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 +
|
||||
;; 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
|
||||
;; executing the macro later on (but that's controversial...)
|
||||
|
||||
(defun kmacro-bind-to-key (arg)
|
||||
"When not defining or executing a macro, offer to bind last macro to a key."
|
||||
"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
|
||||
one of these sequences, just enter the digit or letter, rather than
|
||||
the whole sequence.
|
||||
|
||||
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."
|
||||
(interactive "p")
|
||||
(if (or defining-kbd-macro executing-kbd-macro)
|
||||
(if defining-kbd-macro
|
||||
(message "Cannot save macro while defining it."))
|
||||
(unless last-kbd-macro
|
||||
(error "No keyboard macro defined"))
|
||||
(let ((key-seq (read-key-sequence "Bind last macro to key: ")))
|
||||
(unless (equal key-seq "")
|
||||
(define-key global-map key-seq last-kbd-macro)))))
|
||||
(let ((key-seq (read-key-sequence "Bind last macro to key: "))
|
||||
ok cmd)
|
||||
(when (= (length key-seq) 1)
|
||||
(let ((ch (aref key-seq 0)))
|
||||
(if (or (and (>= ch ?0) (<= ch ?9))
|
||||
(and (>= ch ?A) (<= ch ?Z)))
|
||||
(setq key-seq (concat "\C-x\C-k" key-seq)
|
||||
ok t))))
|
||||
(when (and (not (equal key-seq ""))
|
||||
(or ok
|
||||
(not (setq cmd (key-binding key-seq)))
|
||||
(stringp cmd)
|
||||
(vectorp cmd)
|
||||
(yes-or-no-p (format "%s runs command %S. Bind anyway? "
|
||||
(format-kbd-macro key-seq)
|
||||
cmd))))
|
||||
(define-key global-map key-seq last-kbd-macro)
|
||||
(message "Keyboard macro bound to %s" (format-kbd-macro key-seq))))))
|
||||
|
||||
|
||||
(defun kmacro-view-macro (&optional arg)
|
||||
"Display the last keyboard macro."
|
||||
"Display the last keyboard macro.
|
||||
If repeated, it shows previous elements in the macro ring."
|
||||
(interactive)
|
||||
(kmacro-display last-kbd-macro))
|
||||
|
||||
(cond
|
||||
((or (kmacro-ring-empty-p)
|
||||
(not (eq last-command 'kmacro-view-macro)))
|
||||
(setq kmacro-view-last-item nil))
|
||||
((null kmacro-view-last-item)
|
||||
(setq kmacro-view-last-item kmacro-ring
|
||||
kmacro-view-item-no 2))
|
||||
((consp kmacro-view-last-item)
|
||||
(setq kmacro-view-last-item (cdr kmacro-view-last-item)
|
||||
kmacro-view-item-no (1+ kmacro-view-item-no)))
|
||||
(t
|
||||
(setq kmacro-view-last-item nil)))
|
||||
(setq this-command 'kmacro-view-macro
|
||||
last-command this-command) ;; in case we repeat
|
||||
(kmacro-display (if kmacro-view-last-item
|
||||
(car (car kmacro-view-last-item))
|
||||
last-kbd-macro)
|
||||
nil
|
||||
(if kmacro-view-last-item
|
||||
(concat (cond ((= kmacro-view-item-no 2) "2nd")
|
||||
((= kmacro-view-item-no 3) "3nd")
|
||||
(t (format "%dth" kmacro-view-item-no)))
|
||||
" previous macro")
|
||||
"Last macro")))
|
||||
|
||||
(defun kmacro-view-macro-repeat (&optional arg)
|
||||
"Like `kmacro-view-macro', but allow repeat without repeating prefix."
|
||||
"Display the last keyboard macro.
|
||||
If repeated, it shows previous elements in the macro ring.
|
||||
To execute the displayed macro ring item without changing the macro ring,
|
||||
just enter C-k.
|
||||
This is like `kmacro-view-macro', but allows repeating macro commands
|
||||
without repeating the prefix."
|
||||
(interactive)
|
||||
(let ((keys (kmacro-get-repeat-prefix)))
|
||||
(kmacro-view-macro arg)
|
||||
(if (and last-kbd-macro keys)
|
||||
(kmacro-repeat-on-last-key keys))))
|
||||
|
||||
(put 'kmacro-view-macro-repeat 'kmacro-repeat 'head)
|
||||
(put 'kmacro-view-macro-repeat 'kmacro-repeat 'ring)
|
||||
|
||||
|
||||
(defun kmacro-edit-macro-repeat (&optional arg)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue