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