Merge from trunk
[bpt/emacs.git] / lisp / macros.el
CommitLineData
55535639 1;;; macros.el --- non-primitive commands for keyboard macros
6594deb0 2
95df8112
GM
3;; Copyright (C) 1985-1987, 1992, 1994-1995, 2001-2011
4;; Free Software Foundation, Inc.
a2535589 5
9750e079 6;; Maintainer: FSF
e9571d2a 7;; Keywords: abbrev
bd78fa1d 8;; Package: emacs
9750e079 9
a2535589
JA
10;; This file is part of GNU Emacs.
11
eb3fa2cf 12;; GNU Emacs is free software: you can redistribute it and/or modify
a2535589 13;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
a2535589
JA
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
eb3fa2cf 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
a2535589 24
e41b2db1
ER
25;;; Commentary:
26
27;; Extension commands for keyboard macros. These permit you to assign
28;; a name to the last-defined keyboard macro, expand and insert the
29;; lisp corresponding to a macro, query the user from within a macro,
30;; or apply a macro to each line in the reason.
31
e5167999 32;;; Code:
a2535589 33
7229064d 34;;;###autoload
a2535589
JA
35(defun name-last-kbd-macro (symbol)
36 "Assign a name to the last keyboard macro defined.
ac5b56bc 37Argument SYMBOL is the name to define.
a2535589 38The symbol's function definition becomes the keyboard macro string.
540671f3 39Such a \"function\" cannot be called from Lisp, but it is a valid editor command."
a2535589
JA
40 (interactive "SName for last kbd macro: ")
41 (or last-kbd-macro
42 (error "No keyboard macro defined"))
43 (and (fboundp symbol)
44 (not (stringp (symbol-function symbol)))
4dc7458e 45 (not (vectorp (symbol-function symbol)))
55535639 46 (error "Function %s is already defined and not a keyboard macro"
a2535589 47 symbol))
a3fc4dee
RS
48 (if (string-equal symbol "")
49 (error "No command name given"))
a2535589
JA
50 (fset symbol last-kbd-macro))
51
7229064d 52;;;###autoload
a2535589
JA
53(defun insert-kbd-macro (macroname &optional keys)
54 "Insert in buffer the definition of kbd macro NAME, as Lisp code.
540671f3 55Optional second arg KEYS means also record the keys it is on
b4b3b736 56\(this is the prefix argument, when calling interactively).
a2535589 57
540671f3
RS
58This Lisp code will, when executed, define the kbd macro with the same
59definition it has now. If you say to record the keys, the Lisp code
60will also rebind those keys to the macro. Only global key bindings
61are recorded since executing this Lisp code always makes global
62bindings.
a2535589 63
b4b3b736 64To save a kbd macro, visit a file of Lisp code such as your `~/.emacs',
a2535589 65use this command, and then save the file."
5edd7c33
KS
66 (interactive (list (intern (completing-read "Insert kbd macro (name): "
67 obarray
4d79b874
EZ
68 (lambda (elt)
69 (and (fboundp elt)
70 (or (stringp (symbol-function elt))
5edd7c33
KS
71 (vectorp (symbol-function elt))
72 (get elt 'kmacro))))
4d79b874
EZ
73 t))
74 current-prefix-arg))
45ca32a6
RS
75 (let (definition)
76 (if (string= (symbol-name macroname) "")
77 (progn
78 (setq macroname 'last-kbd-macro definition last-kbd-macro)
79 (insert "(setq "))
80 (setq definition (symbol-function macroname))
81 (insert "(fset '"))
82 (prin1 macroname (current-buffer))
83 (insert "\n ")
157d78ec
KH
84 (if (stringp definition)
85 (let ((beg (point)) end)
86 (prin1 definition (current-buffer))
87 (setq end (point-marker))
88 (goto-char beg)
f0653de7
RS
89 (while (< (point) end)
90 (let ((char (following-char)))
91 (cond ((= char 0)
92 (delete-region (point) (1+ (point)))
93 (insert "\\C-@"))
94 ((< char 27)
95 (delete-region (point) (1+ (point)))
96 (insert "\\C-" (+ 96 char)))
97 ((= char ?\C-\\)
98 (delete-region (point) (1+ (point)))
99 (insert "\\C-\\\\"))
100 ((< char 32)
101 (delete-region (point) (1+ (point)))
102 (insert "\\C-" (+ 64 char)))
103 ((< char 127)
104 (forward-char 1))
105 ((= char 127)
106 (delete-region (point) (1+ (point)))
107 (insert "\\C-?"))
108 ((= char 128)
109 (delete-region (point) (1+ (point)))
110 (insert "\\M-\\C-@"))
111 ((= char (aref "\M-\C-\\" 0))
112 (delete-region (point) (1+ (point)))
113 (insert "\\M-\\C-\\\\"))
114 ((< char 155)
115 (delete-region (point) (1+ (point)))
116 (insert "\\M-\\C-" (- char 32)))
117 ((< char 160)
118 (delete-region (point) (1+ (point)))
119 (insert "\\M-\\C-" (- char 64)))
120 ((= char (aref "\M-\\" 0))
121 (delete-region (point) (1+ (point)))
122 (insert "\\M-\\\\"))
123 ((< char 255)
124 (delete-region (point) (1+ (point)))
125 (insert "\\M-" (- char 128)))
126 ((= char 255)
127 (delete-region (point) (1+ (point)))
157d78ec
KH
128 (insert "\\M-\\C-?"))))))
129 (if (vectorp definition)
07d1e73a 130 (let ((len (length definition)) (i 0) char mods)
157d78ec 131 (while (< i len)
0c655b90 132 (insert (if (zerop i) ?\[ ?\s))
157d78ec
KH
133 (setq char (aref definition i)
134 i (1+ i))
59f36859
SM
135 (if (not (numberp char))
136 (prin1 char (current-buffer))
137 (princ (prin1-char char) (current-buffer))))
157d78ec
KH
138 (insert ?\]))
139 (prin1 definition (current-buffer))))
45ca32a6
RS
140 (insert ")\n")
141 (if keys
233f0c9f
CY
142 (let ((keys (where-is-internal (symbol-function macroname)
143 '(keymap))))
45ca32a6
RS
144 (while keys
145 (insert "(global-set-key ")
146 (prin1 (car keys) (current-buffer))
147 (insert " '")
148 (prin1 macroname (current-buffer))
149 (insert ")\n")
150 (setq keys (cdr keys)))))))
a2535589 151
7229064d 152;;;###autoload
a2535589
JA
153(defun kbd-macro-query (flag)
154 "Query user during kbd macro execution.
540671f3
RS
155 With prefix argument, enters recursive edit, reading keyboard
156commands even within a kbd macro. You can give different commands
157each time the macro executes.
ba790870
RS
158 Without prefix argument, asks whether to continue running the macro.
159Your options are: \\<query-replace-map>
160\\[act] Finish this iteration normally and continue with the next.
161\\[skip] Skip the rest of this iteration, and start the next.
162\\[exit] Stop the macro entirely right now.
163\\[recenter] Redisplay the screen, then ask again.
164\\[edit] Enter recursive edit; ask again when you exit from that."
a2535589 165 (interactive "P")
efcf38c7 166 (or executing-kbd-macro
a2535589
JA
167 defining-kbd-macro
168 (error "Not defining or executing kbd macro"))
169 (if flag
efcf38c7 170 (let (executing-kbd-macro defining-kbd-macro)
a2535589 171 (recursive-edit))
efcf38c7 172 (if (not executing-kbd-macro)
a2535589 173 nil
af400c00
RS
174 (let ((loop t)
175 (msg (substitute-command-keys
176 "Proceed with macro?\\<query-replace-map>\
8693344e 177 (\\[act], \\[skip], \\[exit], \\[recenter], \\[edit]) ")))
a2535589 178 (while loop
efcf38c7 179 (let ((key (let ((executing-kbd-macro nil)
af400c00 180 (defining-kbd-macro nil))
8700ec61 181 (message "%s" msg)
af400c00
RS
182 (read-event)))
183 def)
184 (setq key (vector key))
185 (setq def (lookup-key query-replace-map key))
186 (cond ((eq def 'act)
a2535589 187 (setq loop nil))
af400c00 188 ((eq def 'skip)
a2535589 189 (setq loop nil)
efcf38c7 190 (setq executing-kbd-macro ""))
af400c00 191 ((eq def 'exit)
a2535589 192 (setq loop nil)
efcf38c7 193 (setq executing-kbd-macro t))
af400c00 194 ((eq def 'recenter)
a2535589 195 (recenter nil))
af400c00 196 ((eq def 'edit)
efcf38c7 197 (let (executing-kbd-macro defining-kbd-macro)
af400c00
RS
198 (recursive-edit)))
199 ((eq def 'quit)
200 (setq quit-flag t))
201 (t
202 (or (eq def 'help)
203 (ding))
204 (with-output-to-temp-buffer "*Help*"
205 (princ
206 (substitute-command-keys
eb8c3be9 207 "Specify how to proceed with keyboard macro execution.
af400c00
RS
208Possibilities: \\<query-replace-map>
209\\[act] Finish this iteration normally and continue with the next.
210\\[skip] Skip the rest of this iteration, and start the next.
211\\[exit] Stop the macro entirely right now.
212\\[recenter] Redisplay the screen, then ask again.
6ec1c571 213\\[edit] Enter recursive edit; ask again when you exit from that."))
7fdbcd83 214 (with-current-buffer standard-output
6ec1c571 215 (help-mode)))))))))))
7229064d 216
63c86e17
JB
217;;;###autoload
218(defun apply-macro-to-region-lines (top bottom &optional macro)
2b1c8da0
LT
219 "Apply last keyboard macro to all lines in the region.
220For each line that begins in the region, move to the beginning of
221the line, and run the last keyboard macro.
63c86e17
JB
222
223When called from lisp, this function takes two arguments TOP and
224BOTTOM, describing the current region. TOP must be before BOTTOM.
225The optional third argument MACRO specifies a keyboard macro to
226execute.
227
228This is useful for quoting or unquoting included text, adding and
229removing comments, or producing tables where the entries are regular.
230
231For example, in Usenet articles, sections of text quoted from another
232author are indented, or have each line start with `>'. To quote a
233section of text, define a keyboard macro which inserts `>', put point
234and mark at opposite ends of the quoted section, and use
235`\\[apply-macro-to-region-lines]' to mark the entire section.
236
237Suppose you wanted to build a keyword table in C where each entry
238looked like this:
239
f1180544 240 { \"foo\", foo_data, foo_function },
63c86e17
JB
241 { \"bar\", bar_data, bar_function },
242 { \"baz\", baz_data, baz_function },
243
244You could enter the names in this format:
245
246 foo
247 bar
248 baz
249
250and write a macro to massage a word into a table entry:
251
252 \\C-x (
253 \\M-d { \"\\C-y\", \\C-y_data, \\C-y_function },
254 \\C-x )
255
256and then select the region of un-tablified names and use
2b1c8da0 257`\\[apply-macro-to-region-lines]' to build the table from the names."
63c86e17 258 (interactive "r")
bcc78bc0
JB
259 (or macro
260 (progn
261 (if (null last-kbd-macro)
55535639 262 (error "No keyboard macro has been defined"))
bcc78bc0 263 (setq macro last-kbd-macro)))
63c86e17 264 (save-excursion
2b1c8da0 265 (let ((end-marker (copy-marker bottom))
5277487d 266 next-line-marker)
63c86e17
JB
267 (goto-char top)
268 (if (not (bolp))
269 (forward-line 1))
5277487d
JB
270 (setq next-line-marker (point-marker))
271 (while (< next-line-marker end-marker)
272 (goto-char next-line-marker)
3d64136f 273 (save-excursion
5277487d
JB
274 (forward-line 1)
275 (set-marker next-line-marker (point)))
276 (save-excursion
f732f824 277 (let ((mark-active nil))
b003beb1 278 (execute-kbd-macro macro))))
5277487d
JB
279 (set-marker end-marker nil)
280 (set-marker next-line-marker nil))))
63c86e17 281
5f5d794a 282;;;###autoload (define-key ctl-x-map "q" 'kbd-macro-query)
6594deb0 283
896546cd
RS
284(provide 'macros)
285
6594deb0 286;;; macros.el ends here