Commit | Line | Data |
---|---|---|
5a7f5d07 | 1 | /* Keyboard macros. |
c6c5df7f | 2 | Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc. |
5a7f5d07 JB |
3 | |
4 | This file is part of GNU Emacs. | |
5 | ||
6 | GNU Emacs is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
502ddf23 | 8 | the Free Software Foundation; either version 2, or (at your option) |
5a7f5d07 JB |
9 | any later version. |
10 | ||
11 | GNU Emacs is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU Emacs; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
20 | ||
18160b98 | 21 | #include <config.h> |
5a7f5d07 JB |
22 | #include "lisp.h" |
23 | #include "macros.h" | |
24 | #include "commands.h" | |
25 | #include "buffer.h" | |
26 | #include "window.h" | |
077d751f | 27 | #include "keyboard.h" |
5a7f5d07 JB |
28 | |
29 | Lisp_Object Qexecute_kbd_macro; | |
30 | ||
5a7f5d07 JB |
31 | Lisp_Object Vexecuting_macro; |
32 | int executing_macro_index; | |
33 | ||
34 | Lisp_Object Fexecute_kbd_macro (); | |
35 | \f | |
36 | DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 1, "P", | |
37 | "Record subsequent keyboard input, defining a keyboard macro.\n\ | |
38 | The commands are recorded even as they are executed.\n\ | |
39 | Use \\[end-kbd-macro] to finish recording and make the macro available.\n\ | |
40 | Use \\[name-last-kbd-macro] to give it a permanent name.\n\ | |
41 | Non-nil arg (prefix arg) means append to last macro defined;\n\ | |
42 | This begins by re-executing that macro as if you typed it again.") | |
43 | (append) | |
44 | Lisp_Object append; | |
45 | { | |
cd8b5aa3 | 46 | if (!NILP (current_kboard->defining_kbd_macro)) |
5a7f5d07 JB |
47 | error ("Already defining kbd macro"); |
48 | ||
cd8b5aa3 | 49 | if (!current_kboard->kbd_macro_buffer) |
8b97da83 | 50 | { |
cd8b5aa3 KH |
51 | current_kboard->kbd_macro_bufsize = 30; |
52 | current_kboard->kbd_macro_buffer | |
8b97da83 KH |
53 | = (Lisp_Object *)malloc (30 * sizeof (Lisp_Object)); |
54 | } | |
5a7f5d07 | 55 | update_mode_lines++; |
265a9e55 | 56 | if (NILP (append)) |
5a7f5d07 | 57 | { |
cd8b5aa3 KH |
58 | current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer; |
59 | current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer; | |
5a7f5d07 JB |
60 | message("Defining kbd macro..."); |
61 | } | |
62 | else | |
63 | { | |
64 | message("Appending to kbd macro..."); | |
cd8b5aa3 KH |
65 | current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_end; |
66 | Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, | |
9e1ffae2 | 67 | make_number (1)); |
5a7f5d07 | 68 | } |
cd8b5aa3 | 69 | current_kboard->defining_kbd_macro = Qt; |
5a7f5d07 JB |
70 | |
71 | return Qnil; | |
72 | } | |
73 | ||
74 | DEFUN ("end-kbd-macro", Fend_kbd_macro, Send_kbd_macro, 0, 1, "p", | |
75 | "Finish defining a keyboard macro.\n\ | |
76 | The definition was started by \\[start-kbd-macro].\n\ | |
77 | The macro is now available for use via \\[call-last-kbd-macro],\n\ | |
78 | or it can be given a name with \\[name-last-kbd-macro] and then invoked\n\ | |
79 | under that name.\n\ | |
80 | \n\ | |
81 | With numeric arg, repeat macro now that many times,\n\ | |
82 | counting the definition just completed as the first repetition.\n\ | |
83 | An argument of zero means repeat until error.") | |
84 | (arg) | |
85 | Lisp_Object arg; | |
86 | { | |
cd8b5aa3 KH |
87 | if (NILP (current_kboard->defining_kbd_macro)) |
88 | error ("Not defining kbd macro."); | |
5a7f5d07 | 89 | |
265a9e55 | 90 | if (NILP (arg)) |
a4773b43 | 91 | XSETFASTINT (arg, 1); |
5a7f5d07 JB |
92 | else |
93 | CHECK_NUMBER (arg, 0); | |
94 | ||
cd8b5aa3 | 95 | if (!NILP (current_kboard->defining_kbd_macro)) |
5a7f5d07 | 96 | { |
cd8b5aa3 | 97 | current_kboard->defining_kbd_macro = Qnil; |
5a7f5d07 | 98 | update_mode_lines++; |
cd8b5aa3 KH |
99 | current_kboard->Vlast_kbd_macro |
100 | = make_event_array ((current_kboard->kbd_macro_end | |
101 | - current_kboard->kbd_macro_buffer), | |
102 | current_kboard->kbd_macro_buffer); | |
5a7f5d07 JB |
103 | message("Keyboard macro defined"); |
104 | } | |
105 | ||
106 | if (XFASTINT (arg) == 0) | |
cd8b5aa3 | 107 | Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, arg); |
5a7f5d07 JB |
108 | else |
109 | { | |
e86f81cc JB |
110 | XSETINT (arg, XINT (arg)-1); |
111 | if (XINT (arg) > 0) | |
cd8b5aa3 | 112 | Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, arg); |
5a7f5d07 JB |
113 | } |
114 | return Qnil; | |
115 | } | |
116 | ||
117 | /* Store character c into kbd macro being defined */ | |
118 | ||
119 | store_kbd_macro_char (c) | |
120 | Lisp_Object c; | |
121 | { | |
cd8b5aa3 | 122 | if (!NILP (current_kboard->defining_kbd_macro)) |
5a7f5d07 | 123 | { |
cd8b5aa3 KH |
124 | if ((current_kboard->kbd_macro_ptr |
125 | - current_kboard->kbd_macro_buffer) | |
126 | == current_kboard->kbd_macro_bufsize) | |
5a7f5d07 | 127 | { |
8b97da83 | 128 | register Lisp_Object *new; |
cd8b5aa3 KH |
129 | current_kboard->kbd_macro_bufsize *= 2; |
130 | new = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer, | |
131 | (current_kboard->kbd_macro_bufsize | |
8b97da83 | 132 | * sizeof (Lisp_Object))); |
cd8b5aa3 KH |
133 | current_kboard->kbd_macro_ptr |
134 | += new - current_kboard->kbd_macro_buffer; | |
135 | current_kboard->kbd_macro_end | |
136 | += new - current_kboard->kbd_macro_buffer; | |
137 | current_kboard->kbd_macro_buffer = new; | |
5a7f5d07 | 138 | } |
cd8b5aa3 | 139 | *current_kboard->kbd_macro_ptr++ = c; |
5a7f5d07 JB |
140 | } |
141 | } | |
142 | ||
143 | /* Declare that all chars stored so far in the kbd macro being defined | |
144 | really belong to it. This is done in between editor commands. */ | |
145 | ||
146 | finalize_kbd_macro_chars () | |
147 | { | |
cd8b5aa3 | 148 | current_kboard->kbd_macro_end = current_kboard->kbd_macro_ptr; |
5a7f5d07 | 149 | } |
199afd29 RS |
150 | |
151 | DEFUN ("cancel-kbd-macro-events", Fcancel_kbd_macro_events, | |
152 | Scancel_kbd_macro_events, 0, 0, 0, | |
153 | "Cancel the events added to a keyboard macro for this command.") | |
154 | () | |
155 | { | |
156 | current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_end; | |
157 | } | |
2d5f65a9 KH |
158 | |
159 | DEFUN ("store-kbd-macro-event", Fstore_kbd_macro_event, | |
160 | Sstore_kbd_macro_event, 1, 1, 0, | |
161 | "Store EVENT into the keyboard macro being defined.") | |
162 | (event) | |
163 | Lisp_Object event; | |
164 | { | |
165 | store_kbd_macro_char (event); | |
166 | return Qnil; | |
167 | } | |
5a7f5d07 JB |
168 | \f |
169 | DEFUN ("call-last-kbd-macro", Fcall_last_kbd_macro, Scall_last_kbd_macro, | |
170 | 0, 1, "p", | |
171 | "Call the last keyboard macro that you defined with \\[start-kbd-macro].\n\ | |
172 | \n\ | |
173 | A prefix argument serves as a repeat count. Zero means repeat until error.\n\ | |
174 | \n\ | |
175 | To make a macro permanent so you can call it even after\n\ | |
176 | defining others, use \\[name-last-kbd-macro].") | |
177 | (prefix) | |
178 | Lisp_Object prefix; | |
179 | { | |
cd8b5aa3 | 180 | if (! NILP (current_kboard->defining_kbd_macro)) |
5a7f5d07 | 181 | error ("Can't execute anonymous macro while defining one"); |
cd8b5aa3 | 182 | else if (NILP (current_kboard->Vlast_kbd_macro)) |
5a7f5d07 JB |
183 | error ("No kbd macro has been defined"); |
184 | else | |
cd8b5aa3 | 185 | Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, prefix); |
5a7f5d07 JB |
186 | return Qnil; |
187 | } | |
188 | ||
189 | /* Restore Vexecuting_macro and executing_macro_index - called when | |
190 | the unwind-protect in Fexecute_kbd_macro gets invoked. */ | |
191 | static Lisp_Object | |
192 | pop_kbd_macro (info) | |
193 | Lisp_Object info; | |
194 | { | |
195 | Lisp_Object tem; | |
196 | Vexecuting_macro = Fcar (info); | |
197 | tem = Fcdr (info); | |
198 | executing_macro_index = XINT (tem); | |
199 | return Qnil; | |
200 | } | |
201 | ||
202 | DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 2, 0, | |
203 | "Execute MACRO as string of editor command characters.\n\ | |
204 | If MACRO is a symbol, its function definition is used.\n\ | |
205 | COUNT is a repeat count, or nil for once, or 0 for infinite loop.") | |
206 | (macro, prefixarg) | |
207 | Lisp_Object macro, prefixarg; | |
208 | { | |
209 | Lisp_Object final; | |
210 | Lisp_Object tem; | |
211 | int count = specpdl_ptr - specpdl; | |
212 | int repeat = 1; | |
213 | struct gcpro gcpro1; | |
214 | ||
265a9e55 | 215 | if (!NILP (prefixarg)) |
5a7f5d07 JB |
216 | prefixarg = Fprefix_numeric_value (prefixarg), |
217 | repeat = XINT (prefixarg); | |
218 | ||
502ddf23 | 219 | final = indirect_function (macro); |
65346ae6 | 220 | if (!STRINGP (final) && !VECTORP (final)) |
5a7f5d07 JB |
221 | error ("Keyboard macros must be strings or vectors."); |
222 | ||
a4773b43 | 223 | XSETFASTINT (tem, executing_macro_index); |
5a7f5d07 JB |
224 | tem = Fcons (Vexecuting_macro, tem); |
225 | record_unwind_protect (pop_kbd_macro, tem); | |
226 | ||
227 | GCPRO1 (final); | |
228 | do | |
229 | { | |
230 | Vexecuting_macro = final; | |
231 | executing_macro_index = 0; | |
232 | ||
04609ce4 | 233 | current_kboard->Vprefix_arg = Qnil; |
5a7f5d07 | 234 | command_loop_1 (); |
e86f81cc JB |
235 | |
236 | QUIT; | |
5a7f5d07 | 237 | } |
65346ae6 KH |
238 | while (--repeat |
239 | && (STRINGP (Vexecuting_macro) || VECTORP (Vexecuting_macro))); | |
5a7f5d07 JB |
240 | |
241 | UNGCPRO; | |
242 | return unbind_to (count, Qnil); | |
243 | } | |
244 | \f | |
245 | init_macros () | |
246 | { | |
5a7f5d07 JB |
247 | Vexecuting_macro = Qnil; |
248 | } | |
249 | ||
250 | syms_of_macros () | |
251 | { | |
5a7f5d07 JB |
252 | Qexecute_kbd_macro = intern ("execute-kbd-macro"); |
253 | staticpro (&Qexecute_kbd_macro); | |
254 | ||
255 | defsubr (&Sstart_kbd_macro); | |
256 | defsubr (&Send_kbd_macro); | |
257 | defsubr (&Scall_last_kbd_macro); | |
258 | defsubr (&Sexecute_kbd_macro); | |
199afd29 | 259 | defsubr (&Scancel_kbd_macro_events); |
2d5f65a9 | 260 | defsubr (&Sstore_kbd_macro_event); |
5a7f5d07 | 261 | |
cd8b5aa3 | 262 | DEFVAR_KBOARD ("defining-kbd-macro", defining_kbd_macro, |
5a7f5d07 JB |
263 | "Non-nil while a keyboard macro is being defined. Don't set this!"); |
264 | ||
265 | DEFVAR_LISP ("executing-macro", &Vexecuting_macro, | |
9e1ffae2 | 266 | "Currently executing keyboard macro (string or vector); nil if none executing."); |
5a7f5d07 JB |
267 | |
268 | DEFVAR_LISP_NOPRO ("executing-kbd-macro", &Vexecuting_macro, | |
9e1ffae2 | 269 | "Currently executing keyboard macro (string or vector); nil if none executing."); |
5a7f5d07 | 270 | |
cd8b5aa3 | 271 | DEFVAR_KBOARD ("last-kbd-macro", Vlast_kbd_macro, |
9e1ffae2 | 272 | "Last kbd macro defined, as a string or vector; nil if none defined."); |
5a7f5d07 JB |
273 | } |
274 | ||
275 | keys_of_macros () | |
276 | { | |
277 | initial_define_key (control_x_map, ('e'), "call-last-kbd-macro"); | |
278 | initial_define_key (control_x_map, ('('), "start-kbd-macro"); | |
279 | initial_define_key (control_x_map, (')'), "end-kbd-macro"); | |
280 | } |