*** empty log message ***
[bpt/emacs.git] / lisp / kmacro.el
CommitLineData
c30c4abe
KS
1;;; kmacro.el --- enhanced keyboard macros
2
306d2bb3 3;; Copyright (C) 2002 Free Software Foundation, Inc.
c30c4abe
KS
4
5;; Author: Kim F. Storm <storm@cua.dk>
306d2bb3 6;; Keywords: keyboard convenience
c30c4abe
KS
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 2, or (at your option)
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
24
25;;; Commentary:
26
27;; The kmacro package is an alternative user interface to emacs'
28;; keyboard macro functionality. This functionality is normally bound
7e30f58e 29;; to C-x (, C-x ), and C-x e, but these bindings are too hard to
c30c4abe
KS
30;; type to be really useful for doing small repeated tasks.
31
32;; With kmacro, two function keys are dedicated to keyboard macros,
33;; by default F7 and F8. Personally, I prefer F1 and F2, but those
34;; keys already have default bindings.
35;;
36;; To start defining a keyboard macro, use F7. To end the macro,
37;; use F8, and to call the macro also use F8. This makes it very
38;; easy to repeat a macro immediately after defining it.
39;;
40;; You can call the macro repeatedly by pressing F8 multiple times, or
41;; you can give a numeric prefix argument specifying the number of
42;; times to repeat the macro. Macro execution automatically
43;; terminates when point reaches the end of the buffer or if an error
44;; is signalled by ringing the bell.
45
46;; If you enter F7 while defining the macro, the numeric value of
47;; `kmacro-counter' is inserted using the `kmacro-counter-format', and
48;; `kmacro-counter' is incremented by 1 (or the numeric prefix value
49;; of F7).
50;;
51;; The initial value of `kmacro-counter' is 0, or the numeric prefix
52;; value given to F7 when starting the macro.
53;;
54;; Now, each time you call the macro using F8, the current
55;; value of `kmacro-counter' is inserted and incremented, making it
56;; easy to insert incremental numbers in the buffer.
57;;
58;; Example:
59;;
60;; The following sequence: M-5 F7 x M-2 F7 y F8 F8 F8 F8
61;; inserts the following string: x5yx7yx9yx11y
62
7e30f58e 63;; A macro can also be called using a mouse click, default S-mouse-3.
c30c4abe
KS
64;; This calls the macro at the point where you click the mouse.
65
66;; When you have defined another macro, which is thus called via F8,
67;; the previous macro is pushed onto a keyboard macro ring. The head
68;; macro on the ring can be executed using S-F8. You can cycle the
69;; macro ring using C-F8. You can also swap the last macro and the
70;; head of the macro ring using C-u F8.
71
72;; You can edit the last macro using M-F7.
73
74;; You can append to the last macro using C-u F7.
75
76;; You can set the macro counter using C-F7, and you can set
77;; the macro counter format with S-F7..
78
79;; The following key bindings are performed:
80;;
81;; Normal While defining macro
82;; --------------------------- ------------------------------
83;; f7 Define macro Insert current counter value
84;; Prefix arg specifies initial and increase counter by prefix
85;; counter value (default 0) (default increment: 1)
86;;
87;; C-u f7 APPENDs to last macro
88;;
89;; f8 Call last macro End macro
90;; Prefix arg specifies number
91;; of times to execute macro.
92;;
93;; C-u f8 Swap last and head of macro ring.
94;;
95;; S-f7 Set the format of the macro Ditto, but notice that the
96;; counter (default: %d). format is reset at the next
97;; invocation of the macro.
98;;
99;; C-f7 Set the macro counter value Increase/decrease counter value
100;; to the prefix value. by the prefix value, or if prefix
101;; is C-u, set counter to 0.
102;;
103;; M-f7 Edit the last macro.
104;;
105;; S-f8 Call the previous macro.
106;;
107;; C-f8 Cycle the macro ring.
108;;
109;; S-mouse-3 Set point at click and End macro and execute macro at
110;; execute last macro. click.
111
112;;; Code:
113
7e30f58e 114;; Customization:
c30c4abe
KS
115
116(defgroup kmacro nil
117 "Simplified keyboard macro user interface."
118 :group 'keyboard
119 :group 'convenience
120 :link '(emacs-commentary-link :tag "Commentary" "kmacro.el")
121 :link '(emacs-library-link :tag "Lisp File" "kmacro.el"))
122
123;;;###autoload
124(defcustom kmacro-initialize nil
125 "Setting this variable turns on the kmacro functionality.
7e30f58e 126This binds the kmacro function keys in the `global-map', so
c30c4abe
KS
127unsetting this variable does not have any effect!"
128 :set #'(lambda (symbol value)
129 (if value (kmacro-initialize))
130 (set symbol value))
131 :initialize 'custom-initialize-default
132 :require 'kmacro
133 :link '(emacs-commentary-link "kmacro.el")
134 :set-after '(kmacro-start-key kmacro-call-key kmacro-mouse-button)
135 :version "21.4"
136 :type 'boolean
137 :group 'kmacro)
138
139(defcustom kmacro-start-key 'f7
140 "The function key used by kmacro to start a macro."
141 :type 'symbol
142 :group 'kmacro)
143
144(defcustom kmacro-call-key 'f8
145 "The function key used by kmacro to end and call a macro."
146 :type 'symbol
147 :group 'kmacro)
148
149(defcustom kmacro-call-mouse-event 'S-mouse-3
150 "The mouse event used by kmacro to call a macro."
151 :type 'symbol
152 :group 'kmacro)
153
154;; State variables
155
156(defvar kmacro-counter 0
7e30f58e 157 "*Current keyboard macro counter.")
c30c4abe
KS
158
159(defvar kmacro-counter-format "%d"
7e30f58e 160 "*Current keyboard macro counter format.")
c30c4abe
KS
161
162(defvar kmacro-counter-format-start kmacro-counter-format
163 "Macro format at start of macro execution.")
164
7e30f58e
SM
165(defvar kmacro-last-counter 0 "Last counter inserted by key macro.")
166(defvar kmacro-append-to nil "Last key macro if appending to macro.")
167(defvar kmacro-ring nil "Key macro ring.")
c30c4abe
KS
168
169(defvar kmacro-ring-max 4
7e30f58e 170 "*Maximum number of key macros to save in key macro ring.")
c30c4abe
KS
171
172(defun kmacro-display (macro)
7e30f58e 173 "Display a keyboard MACRO."
c30c4abe
KS
174 (let (s)
175 (if (stringp macro)
176 (setq s (if (> (length macro) 50)
177 (concat (substring macro 0 50) "...")
178 macro))
179 (if (vectorp macro)
180 (let (v (i 0) (n (length macro)))
181 (setq s "")
182 (while (and (< i n) (< (length s) 50))
183 (setq v (aref macro i))
184 (setq s (cond
185 ((numberp v) (concat s (char-to-string v)))
186 ((stringp v) (concat s v))
187 ((symbolp v) (concat s "[" (symbol-name v) "]"))
188 (t s)))
189 (setq i (1+ i)))
190 (if (< i n)
191 (setq s (concat s "..."))))))
192 (message (format "Macro: %s" s))))
193
194
195(defun kmacro-start-macro (arg)
7e30f58e 196 "Set `kmacro-counter' to ARG or 0 if missing, and `start-kbd-macro'.
c30c4abe
KS
197With \\[universal-argument], append to current keyboard macro (keep kmacro-counter).
198
199When defining/executing macro, insert macro counter and increment with
200ARG or 1 if missing.
201With \\[universal-argument], insert previous kmacro-counter (but do not modify counter).
202
203The macro counter can be modified via \\[kmacro-set-counter].
204The format of the counter can be modified via \\[kmacro-set-format]."
205 (interactive "p")
206 (if (or defining-kbd-macro executing-kbd-macro)
207 (if (and current-prefix-arg (listp current-prefix-arg))
208 (insert (format kmacro-counter-format kmacro-last-counter))
209 (insert (format kmacro-counter-format kmacro-counter))
210 (setq kmacro-last-counter kmacro-counter
211 kmacro-counter (+ kmacro-counter arg)))
212 (if (and current-prefix-arg (listp current-prefix-arg))
213 (setq kmacro-append-to last-kbd-macro)
214 (setq kmacro-append-to nil
215 kmacro-counter (if current-prefix-arg arg 0)
216 kmacro-last-counter kmacro-counter))
217 (if last-kbd-macro
218 (let ((len (length kmacro-ring)))
219 (setq kmacro-ring (cons last-kbd-macro kmacro-ring))
220 (if (>= len kmacro-ring-max)
221 (setcdr (nthcdr len kmacro-ring) nil))))
222 (setq kmacro-counter-format-start kmacro-counter-format)
223 (start-kbd-macro nil)
224 (if kmacro-append-to (message "Appending to keyboard macro..."))
225))
226
227(defun kmacro-call-macro (arg)
228 "End kbd macro if currently being defined; else call last kbd macro.
7e30f58e 229With numeric prefix ARG, repeat macro that many times.
c30c4abe
KS
230With \\[universal-argument], swap current macro with head of macro ring."
231 (interactive "p")
232 (cond
233 (defining-kbd-macro
234 (end-kbd-macro)
235 (if kmacro-append-to
236 (setq last-kbd-macro (concat kmacro-append-to last-kbd-macro)
237 kmacro-append-to nil)))
238 ((and current-prefix-arg (listp current-prefix-arg))
239 (when kmacro-ring
240 (let ((head (car kmacro-ring)))
241 (setq kmacro-ring (cons last-kbd-macro (cdr kmacro-ring)))
242 (setq last-kbd-macro head)))
243 (kmacro-display last-kbd-macro))
244 (t
245 (setq kmacro-counter-format kmacro-counter-format-start)
246 (call-last-kbd-macro arg))))
247
248(defun kmacro-call-macro-ring (arg)
249 "End kbd macro if currently being defined; else call last kbd macro.
250With \\[universal-argument], display current macro."
251 (interactive "p")
252 (if kmacro-ring
253 (execute-kbd-macro (car kmacro-ring) arg)))
254
255(defun kmacro-end-call-mouse (event)
256 "Move point to the position clicked with the mouse and call last kbd macro.
257If kbd macro currently being defined end it before activating it."
258 (interactive "e")
259 (when defining-kbd-macro
260 (end-kbd-macro)
261 (if kmacro-append-to
262 (setq last-kbd-macro (concat kmacro-append-to last-kbd-macro)
263 kmacro-append-to nil)))
264 (mouse-set-point event)
265 (call-last-kbd-macro nil))
266
267(defun kmacro-cycle-macro-ring (&optional previous)
268 "Cycle the keyboard macro ring on \\[kmacro-call-macro-ring].
269Moves to the next element in the keyboard macro ring.
270With \\[universal-argument] prefix, move to the previous element in the ring.
271Displays the selected macro in the echo area."
272 (interactive "p")
273 (if (null kmacro-ring)
274 (message "No keymacros in ring")
275 (cond
276 ((not (eq this-command last-command))
277 nil)
278 ((= (length kmacro-ring) 1)
279 nil)
280 (previous
281 (let* ((len (length kmacro-ring))
282 (tail (nthcdr (- len 2) kmacro-ring))
283 (elt (car (cdr tail))))
284 (setcdr tail nil)
285 (setq kmacro-ring (cons elt kmacro-ring))))
286 (t
287 (let ((elt (car kmacro-ring)))
288 (setq kmacro-ring (cdr kmacro-ring))
289 (nconc kmacro-ring (list elt)))))
290 (kmacro-display (car kmacro-ring))))
291
292(defun kmacro-save-macro-on-key (arg)
293 "When not defining or executing a macro, offer to save last macro on a key."
294 (interactive "p")
295 (if (or defining-kbd-macro executing-kbd-macro)
296 nil
297 (or last-kbd-macro
298 (error "No keyboard macro defined"))
299 (let ((key-seq (read-key-sequence "Save last macro on key: ")))
300 (or (equal key-seq "\a")
301 (define-key global-map key-seq last-kbd-macro))))
302)
303
304(defun kmacro-set-counter (arg)
305 "Set kmacro-counter to ARG or 0 if missing.
306While defining/executing key macro, increase or decrease counter.
307With \\[universal-argument], unconditionally set counter to 0."
308 (interactive "p")
309 (setq kmacro-counter
310 (cond ((and current-prefix-arg (listp current-prefix-arg)) 0)
311 ((or defining-kbd-macro executing-kbd-macro) (+ kmacro-counter arg))
312 (current-prefix-arg arg)
313 (t 0))))
314
315(defun kmacro-set-format (format)
7e30f58e 316 "Set macro counter FORMAT."
c30c4abe
KS
317 (interactive "sMacro Counter Format (printf format): ")
318 (setq kmacro-counter-format
319 (if (equal format "")
320 "%d"
321 format))
322
323 ;; redefine initial macro counter if we are not executing a macro.
324 (if (not (or defining-kbd-macro executing-kbd-macro))
325 (setq kmacro-counter-format-start kmacro-counter-format))
326)
327
328(defun kmacro-edit-macro ()
329 "Edit keyboard macro."
330 (interactive)
331 (edit-kbd-macro "\r"))
332
333;;;###autoload
334(defun kmacro-initialize (&optional start-key call-key call-mouse)
335 "Setup key bindings for the keyboard macro package.
336If specified, use keys START-KEY, CALL-KEY, and CALL-MOUSE.
337Don't bind to any mouse event if CALL-MOUSE is t.
338Otherwise, use customized keys."
339
340 (setq start-key (or start-key kmacro-start-key 'f7))
341 (setq call-key (or call-key kmacro-call-key 'f8))
342 (setq call-mouse (or call-mouse kmacro-call-mouse-event 'S-mouse-3))
343
344 (global-set-key (vector start-key) 'kmacro-start-macro)
345 (global-set-key (vector (list 'shift start-key)) 'kmacro-set-format)
346 (global-set-key (vector (list 'control start-key)) 'kmacro-set-counter)
347 (global-set-key (vector (list 'meta start-key)) 'kmacro-edit-macro)
348
349 (global-set-key (vector call-key) 'kmacro-call-macro)
350 (global-set-key (vector (list 'shift call-key)) 'kmacro-call-macro-ring)
351 (global-set-key (vector (list 'control call-key)) 'kmacro-cycle-macro-ring)
352
353 (unless (eq call-mouse t)
354 (global-set-key (vector call-mouse) 'kmacro-end-call-mouse)))
355
7e30f58e
SM
356(provide 'kmacro)
357;;; kmacro.el ends here