|
|
1.1 root 1: /* Keyboard macros.
2: Copyright (C) 1985 Richard M. Stallman.
3:
4: This file is part of GNU Emacs.
5:
6: GNU Emacs is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU Emacs General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU Emacs, but only under the conditions described in the
15: GNU Emacs General Public License. A copy of this license is
16: supposed to have been given to you along with GNU Emacs so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: #include "config.h"
23: #include "lisp.h"
24: #include "macros.h"
25: #include "commands.h"
26: #include "buffer.h"
27: #include "window.h"
28:
29: int defining_kbd_macro;
30:
31: char *kbd_macro_buffer;
32: char *kbd_macro_ptr;
33: char *kbd_macro_end;
34: int kbd_macro_bufsize;
35: Lisp_Object Vlast_kbd_macro;
36:
37: Lisp_Object Vexecuting_macro;
38: int executing_macro_index;
39:
40: Lisp_Object Fexecute_kbd_macro ();
41:
42: DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 1, "P",
43: "Record subsequent keyboard input, defining a keyboard macro.\n\
44: The commands are recorded even as they are executed.\n\
45: Use \\[end-kbd-macro] to finish recording and make the macro available.\n\
46: Use \\[name-last-kbd-macro] to give it a permanent name.\n\
47: Non-nil arg (prefix arg) means append to last macro defined;\n\
48: This begins by re-executing that macro as if you typed it again.")
49: (append)
50: Lisp_Object append;
51: {
52: if (defining_kbd_macro)
53: error ("Already defining kbd macro!");
54: else
55: {
56: defining_kbd_macro++;
57: RedoModes++;
58: if (NULL (append))
59: {
60: kbd_macro_ptr = kbd_macro_buffer;
61: kbd_macro_end = kbd_macro_buffer;
62: message("Defining kbd macro...");
63: }
64: else
65: {
66: message("Appending to kbd macro...");
67: kbd_macro_ptr = kbd_macro_end;
68: Fexecute_kbd_macro (Vlast_kbd_macro, make_number (1));
69: }
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: With numeric arg, repeat macro now that many times,\n\
81: counting the definition just completed as the first repetition.")
82: (arg)
83: Lisp_Object arg;
84: {
85: if (!defining_kbd_macro)
86: error ("Not defining kbd macro.");
87:
88: if (NULL (arg))
89: XFASTINT (arg) = 1;
90: else
91: CHECK_NUMBER (arg, 0);
92:
93: if (defining_kbd_macro)
94: {
95: defining_kbd_macro = 0;
96: RedoModes++;
97: Vlast_kbd_macro = make_string (kbd_macro_buffer,
98: kbd_macro_end - kbd_macro_buffer);
99: message("Keyboard macro defined");
100: }
101:
102: if (XFASTINT (arg) == 0)
103: Fexecute_kbd_macro (Vlast_kbd_macro, arg);
104: else
105: {
106: XFASTINT (arg)--;
107: if (XFASTINT (arg) > 0)
108: Fexecute_kbd_macro (Vlast_kbd_macro, arg);
109: }
110: return Qnil;
111: }
112:
113: /* Store character c into kbd macro being defined */
114:
115: store_kbd_macro_char (c)
116: unsigned char c;
117: {
118: if (defining_kbd_macro)
119: {
120: if (kbd_macro_ptr - kbd_macro_buffer == kbd_macro_bufsize)
121: {
122: register char *new = (char *) xrealloc (kbd_macro_buffer, kbd_macro_bufsize *= 2);
123: kbd_macro_ptr += new - kbd_macro_buffer;
124: kbd_macro_end = new + kbd_macro_bufsize;
125: kbd_macro_buffer = new;
126: }
127: *kbd_macro_ptr++ = c;
128: }
129: }
130:
131: /* Declare that all chars stored so far in the kbd macro being defined
132: really belong to it. This is done in between editor commands. */
133:
134: finalize_kbd_macro_chars ()
135: {
136: kbd_macro_end = kbd_macro_ptr;
137: }
138:
139: DEFUN ("call-last-kbd-macro", Fcall_last_kbd_macro, Scall_last_kbd_macro,
140: 0, 1, "p",
141: "Call the last keyboard macro that you defined with \\[start-kbd-macro].\n\
142: To make a macro permanent so you can call it even after\n\
143: defining others, use \\[name-last-kbd-macro].")
144: (prefix)
145: Lisp_Object prefix;
146: {
147: if (defining_kbd_macro)
148: error ("Can't execute anonymous macro while defining one");
149: else if (NULL (Vlast_kbd_macro))
150: error ("No kbd macro has been defined");
151: else
152: Fexecute_kbd_macro (Vlast_kbd_macro, prefix);
153: return Qnil;
154: }
155:
156: static Lisp_Object
157: pop_kbd_macro (info)
158: Lisp_Object info;
159: {
160: Lisp_Object tem;
161: Vexecuting_macro = Fcar (info);
162: tem = Fcdr (info);
163: executing_macro_index = XINT (tem);
164: return Qnil;
165: }
166:
167: DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 2, 0,
168: "Execute MACRO as string of editor command characters.\n\
169: If MACRO is a symbol, its function definition is used.\n\
170: COUNT is a repeat count, or nil for once, or 0 for infinite loop.")
171: (macro, prefixarg)
172: Lisp_Object macro, prefixarg;
173: {
174: Lisp_Object final;
175: Lisp_Object tem;
176: int count = specpdl_ptr - specpdl;
177: int repeat = 1;
178: struct gcpro gcpro1;
179:
180: if (!NULL (prefixarg))
181: prefixarg = Fprefix_numeric_value (prefixarg),
182: repeat = XINT (prefixarg);
183:
184: final = macro;
185: while (XTYPE (final) == Lisp_Symbol && !EQ (final, Qunbound))
186: final = XSYMBOL (final)->function;
187: CHECK_STRING (final, 0);
188:
189: XFASTINT (tem) = executing_macro_index;
190: tem = Fcons (Vexecuting_macro, tem);
191: record_unwind_protect (pop_kbd_macro, tem);
192:
193: GCPRO1 (final);
194: do
195: {
196: Vexecuting_macro = final;
197: executing_macro_index = 0;
198:
199: command_loop_1 ();
200: }
201: while (--repeat && XTYPE (Vexecuting_macro) == Lisp_String);
202:
203: UNGCPRO;
204: unbind_to (count);
205:
206: return Qnil;
207: }
208:
209: DEFUN ("name-last-kbd-macro", Fname_last_kbd_macro, Sname_last_kbd_macro, 1, 1, "SName last kbd macro: ",
210: "Assign a name to the last keyboard macro defined.\n\
211: One arg, a symbol, which is the name to define.\n\
212: The symbol's function definition becomes the keyboard macro string.\n\
213: Such a \"function\" cannot be called from Lisp, but it is a valid command\n\
214: definition for the editor command loop.")
215: (sym)
216: Lisp_Object sym;
217: {
218: CHECK_SYMBOL (sym, 0);
219:
220: if (defining_kbd_macro)
221: error ("Not allowed to name a keyboard macro while defining one");
222:
223: if (NULL (Vlast_kbd_macro))
224: error ("No keyboard macro defined");
225:
226: Ffset (sym, Vlast_kbd_macro);
227: return sym;
228: }
229:
230: init_macros ()
231: {
232: Vlast_kbd_macro = Qnil;
233: defining_kbd_macro = 0;
234:
235: Vexecuting_macro = Qnil;
236: }
237:
238: syms_of_macros ()
239: {
240: kbd_macro_bufsize = 100;
241: kbd_macro_buffer = (char *) malloc (kbd_macro_bufsize);
242:
243: defsubr (&Sstart_kbd_macro);
244: defsubr (&Send_kbd_macro);
245: defsubr (&Scall_last_kbd_macro);
246: defsubr (&Sexecute_kbd_macro);
247: defsubr (&Sname_last_kbd_macro);
248:
249: DefBoolVar ("defining-kbd-macro", &defining_kbd_macro,
250: "Non-nil means store keyboard input into kbd macro being defined.");
251:
252: DefLispVar ("executing-macro", &Vexecuting_macro,
253: "Currently executing keyboard macro (a string); nil if none executing.");
254:
255: DefLispVar ("executing-kbd-macro", &Vexecuting_macro,
256: "Currently executing keyboard macro (a string); nil if none executing.");
257:
258: DefLispVar ("last-kbd-macro", &Vlast_kbd_macro,
259: "Last kbd macro defined, as a string; nil if none defined.");
260: }
261:
262: keys_of_macros ()
263: {
264: defkey (CtlXmap, ('e'), "call-last-kbd-macro");
265: defkey (CtlXmap, ('('), "start-kbd-macro");
266: defkey (CtlXmap, (')'), "end-kbd-macro");
267: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.