macros.c 11.1 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Keyboard macros.
2
   Copyright (C) 1985, 1986, 1993, 2000, 2001 Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
3 4 5 6 7

This file is part of GNU Emacs.

GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Jim Blandy's avatar
Jim Blandy committed
8
the Free Software Foundation; either version 2, or (at your option)
Jim Blandy's avatar
Jim Blandy committed
9 10 11 12 13 14 15 16 17
any later version.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
18 19
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */
Jim Blandy's avatar
Jim Blandy committed
20 21


22
#include <config.h>
Jim Blandy's avatar
Jim Blandy committed
23 24 25 26 27
#include "lisp.h"
#include "macros.h"
#include "commands.h"
#include "buffer.h"
#include "window.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
28
#include "keyboard.h"
Jim Blandy's avatar
Jim Blandy committed
29

30
Lisp_Object Qexecute_kbd_macro, Qkbd_macro_termination_hook;
Jim Blandy's avatar
Jim Blandy committed
31

32 33
/* Kbd macro currently being executed (a string or vector).  */

Jim Blandy's avatar
Jim Blandy committed
34
Lisp_Object Vexecuting_macro;
35 36 37

/* Index of next character to fetch from that macro.  */

Jim Blandy's avatar
Jim Blandy committed
38 39
int executing_macro_index;

40 41 42 43 44 45 46 47 48 49 50 51 52 53
/* Number of successful iterations so far
   for innermost keyboard macro.
   This is not bound at each level,
   so after an error, it describes the innermost interrupted macro.  */

int executing_macro_iterations;

/* This is the macro that was executing.
   This is not bound at each level,
   so after an error, it describes the innermost interrupted macro.
   We use it only as a kind of flag, so no need to protect it.  */

Lisp_Object executing_macro;

54 55
extern Lisp_Object real_this_command;

Jim Blandy's avatar
Jim Blandy committed
56 57 58 59 60 61 62 63
Lisp_Object Fexecute_kbd_macro ();

DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 1, "P",
  "Record subsequent keyboard input, defining a keyboard macro.\n\
The commands are recorded even as they are executed.\n\
Use \\[end-kbd-macro] to finish recording and make the macro available.\n\
Use \\[name-last-kbd-macro] to give it a permanent name.\n\
Non-nil arg (prefix arg) means append to last macro defined;\n\
Gerd Moellmann's avatar
Gerd Moellmann committed
64
this begins by re-executing that macro as if you typed it again.")
Jim Blandy's avatar
Jim Blandy committed
65 66 67
  (append)
     Lisp_Object append;
{
Karl Heuer's avatar
Karl Heuer committed
68
  if (!NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
69 70
    error ("Already defining kbd macro");

Karl Heuer's avatar
Karl Heuer committed
71
  if (!current_kboard->kbd_macro_buffer)
72
    {
Karl Heuer's avatar
Karl Heuer committed
73 74
      current_kboard->kbd_macro_bufsize = 30;
      current_kboard->kbd_macro_buffer
75
	= (Lisp_Object *)xmalloc (30 * sizeof (Lisp_Object));
76
    }
Jim Blandy's avatar
Jim Blandy committed
77
  update_mode_lines++;
Jim Blandy's avatar
Jim Blandy committed
78
  if (NILP (append))
Jim Blandy's avatar
Jim Blandy committed
79
    {
80 81 82 83
      if (current_kboard->kbd_macro_bufsize > 200)
	{
	  current_kboard->kbd_macro_bufsize = 30;
	  current_kboard->kbd_macro_buffer
84 85
	    = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
				       30 * sizeof (Lisp_Object));
86
	}
Karl Heuer's avatar
Karl Heuer committed
87 88
      current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer;
      current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer;
89
      message ("Defining kbd macro...");
Jim Blandy's avatar
Jim Blandy committed
90 91 92
    }
  else
    {
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
      int i, len;

      /* Check the type of last-kbd-macro in case Lisp code changed it.  */
      if (!STRINGP (current_kboard->Vlast_kbd_macro)
	  && !VECTORP (current_kboard->Vlast_kbd_macro))
	current_kboard->Vlast_kbd_macro
	  = wrong_type_argument (Qarrayp, current_kboard->Vlast_kbd_macro);

      len = XINT (Flength (current_kboard->Vlast_kbd_macro));

      /* Copy last-kbd-macro into the buffer, in case the Lisp code
	 has put another macro there.  */
      if (current_kboard->kbd_macro_bufsize < len + 30)
	{
	  current_kboard->kbd_macro_bufsize = len + 30;
	  current_kboard->kbd_macro_buffer
	    = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
				       (len + 30) * sizeof (Lisp_Object));
	}
      for (i = 0; i < len; i++)
	current_kboard->kbd_macro_buffer[i]
	  = Faref (current_kboard->Vlast_kbd_macro, make_number (i));

      current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer + len;
      current_kboard->kbd_macro_end = current_kboard->kbd_macro_ptr;

      /* Re-execute the macro we are appending to,
	 for consistency of behavior.  */
Karl Heuer's avatar
Karl Heuer committed
121
      Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro,
122
			  make_number (1));
123 124

      message ("Appending to kbd macro...");
Jim Blandy's avatar
Jim Blandy committed
125
    }
Karl Heuer's avatar
Karl Heuer committed
126
  current_kboard->defining_kbd_macro = Qt;
Jim Blandy's avatar
Jim Blandy committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140
  
  return Qnil;
}

DEFUN ("end-kbd-macro", Fend_kbd_macro, Send_kbd_macro, 0, 1, "p",
  "Finish defining a keyboard macro.\n\
The definition was started by \\[start-kbd-macro].\n\
The macro is now available for use via \\[call-last-kbd-macro],\n\
or it can be given a name with \\[name-last-kbd-macro] and then invoked\n\
under that name.\n\
\n\
With numeric arg, repeat macro now that many times,\n\
counting the definition just completed as the first repetition.\n\
An argument of zero means repeat until error.")
141 142
  (repeat)
     Lisp_Object repeat;
Jim Blandy's avatar
Jim Blandy committed
143
{
Karl Heuer's avatar
Karl Heuer committed
144
  if (NILP (current_kboard->defining_kbd_macro))
145
    error ("Not defining kbd macro");
Jim Blandy's avatar
Jim Blandy committed
146

147 148
  if (NILP (repeat))
    XSETFASTINT (repeat, 1);
Jim Blandy's avatar
Jim Blandy committed
149
  else
150
    CHECK_NUMBER (repeat, 0);
Jim Blandy's avatar
Jim Blandy committed
151

Karl Heuer's avatar
Karl Heuer committed
152
  if (!NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
153
    {
Karl Heuer's avatar
Karl Heuer committed
154
      current_kboard->defining_kbd_macro = Qnil;
Jim Blandy's avatar
Jim Blandy committed
155
      update_mode_lines++;
Karl Heuer's avatar
Karl Heuer committed
156 157 158 159
      current_kboard->Vlast_kbd_macro
	= make_event_array ((current_kboard->kbd_macro_end
			     - current_kboard->kbd_macro_buffer),
			    current_kboard->kbd_macro_buffer);
160
      message ("Keyboard macro defined");
Jim Blandy's avatar
Jim Blandy committed
161 162
    }

163 164
  if (XFASTINT (repeat) == 0)
    Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, repeat);
Jim Blandy's avatar
Jim Blandy committed
165 166
  else
    {
167 168 169
      XSETINT (repeat, XINT (repeat)-1);
      if (XINT (repeat) > 0)
	Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, repeat);
Jim Blandy's avatar
Jim Blandy committed
170 171 172 173 174 175
    }
  return Qnil;
}

/* Store character c into kbd macro being defined */

176
void
Jim Blandy's avatar
Jim Blandy committed
177 178 179
store_kbd_macro_char (c)
     Lisp_Object c;
{
180 181 182
  struct kboard *kb = current_kboard;

  if (!NILP (kb->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
183
    {
184
      if (kb->kbd_macro_ptr - kb->kbd_macro_buffer == kb->kbd_macro_bufsize)
Jim Blandy's avatar
Jim Blandy committed
185
	{
186 187 188 189 190 191 192 193 194 195
	  int ptr_offset, end_offset, nbytes;
	  
	  ptr_offset = kb->kbd_macro_ptr - kb->kbd_macro_buffer;
	  end_offset = kb->kbd_macro_end - kb->kbd_macro_buffer;
	  kb->kbd_macro_bufsize *= 2;
	  nbytes = kb->kbd_macro_bufsize * sizeof *kb->kbd_macro_buffer;
	  kb->kbd_macro_buffer
	    = (Lisp_Object *) xrealloc (kb->kbd_macro_buffer, nbytes);
	  kb->kbd_macro_ptr = kb->kbd_macro_buffer + ptr_offset;
	  kb->kbd_macro_end = kb->kbd_macro_buffer + end_offset;
Jim Blandy's avatar
Jim Blandy committed
196
	}
197
      
198
      *kb->kbd_macro_ptr++ = c;
Jim Blandy's avatar
Jim Blandy committed
199 200 201 202 203 204
    }
}

/* Declare that all chars stored so far in the kbd macro being defined
 really belong to it.  This is done in between editor commands.  */

205
void
Jim Blandy's avatar
Jim Blandy committed
206 207
finalize_kbd_macro_chars ()
{
Karl Heuer's avatar
Karl Heuer committed
208
  current_kboard->kbd_macro_end = current_kboard->kbd_macro_ptr;
Jim Blandy's avatar
Jim Blandy committed
209
}
210 211 212 213 214 215 216

DEFUN ("cancel-kbd-macro-events", Fcancel_kbd_macro_events,
       Scancel_kbd_macro_events, 0, 0, 0,
  "Cancel the events added to a keyboard macro for this command.")
  ()
{
  current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_end;
217
  return Qnil;
218
}
219 220 221 222 223 224 225 226 227 228

DEFUN ("store-kbd-macro-event", Fstore_kbd_macro_event,
       Sstore_kbd_macro_event, 1, 1, 0,
  "Store EVENT into the keyboard macro being defined.")
  (event)
     Lisp_Object event;
{
  store_kbd_macro_char (event);
  return Qnil;
}
Jim Blandy's avatar
Jim Blandy committed
229 230 231 232 233 234 235 236 237 238 239 240

DEFUN ("call-last-kbd-macro", Fcall_last_kbd_macro, Scall_last_kbd_macro,
  0, 1, "p",
  "Call the last keyboard macro that you defined with \\[start-kbd-macro].\n\
\n\
A prefix argument serves as a repeat count.  Zero means repeat until error.\n\
\n\
To make a macro permanent so you can call it even after\n\
defining others, use \\[name-last-kbd-macro].")
  (prefix)
     Lisp_Object prefix;
{
241 242
  /* Don't interfere with recognition of the previous command
     from before this macro started.  */
243
  Vthis_command = current_kboard->Vlast_command;
244 245
  /* C-x z after the macro should repeat the macro.  */
  real_this_command = current_kboard->Vlast_kbd_macro;
246

Karl Heuer's avatar
Karl Heuer committed
247
  if (! NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
248
    error ("Can't execute anonymous macro while defining one");
Karl Heuer's avatar
Karl Heuer committed
249
  else if (NILP (current_kboard->Vlast_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
250 251
    error ("No kbd macro has been defined");
  else
Karl Heuer's avatar
Karl Heuer committed
252
    Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, prefix);
253 254 255 256

  /* command_loop_1 sets this to nil before it returns;
     get back the last command within the macro
     so that it can be last, again, after we return.  */
257
  Vthis_command = current_kboard->Vlast_command;
258

Jim Blandy's avatar
Jim Blandy committed
259 260 261 262 263
  return Qnil;
}

/* Restore Vexecuting_macro and executing_macro_index - called when
   the unwind-protect in Fexecute_kbd_macro gets invoked.  */
264

Jim Blandy's avatar
Jim Blandy committed
265 266 267 268 269
static Lisp_Object
pop_kbd_macro (info)
     Lisp_Object info;
{
  Lisp_Object tem;
270 271 272 273
  Vexecuting_macro = XCAR (info);
  tem = XCDR (info);
  executing_macro_index = XINT (XCAR (tem));
  real_this_command = XCDR (tem);
274
  Frun_hooks (1, &Qkbd_macro_termination_hook);
Jim Blandy's avatar
Jim Blandy committed
275 276 277 278 279 280 281
  return Qnil;
}

DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 2, 0,
  "Execute MACRO as string of editor command characters.\n\
If MACRO is a symbol, its function definition is used.\n\
COUNT is a repeat count, or nil for once, or 0 for infinite loop.")
282 283
  (macro, count)
     Lisp_Object macro, count;
Jim Blandy's avatar
Jim Blandy committed
284 285 286
{
  Lisp_Object final;
  Lisp_Object tem;
287
  int pdlcount = specpdl_ptr - specpdl;
Jim Blandy's avatar
Jim Blandy committed
288 289
  int repeat = 1;
  struct gcpro gcpro1;
290
  int success_count = 0;
Jim Blandy's avatar
Jim Blandy committed
291

292 293
  executing_macro_iterations = 0;

294 295 296 297 298
  if (!NILP (count))
    {
      count = Fprefix_numeric_value (count);
      repeat = XINT (count);
    }
Jim Blandy's avatar
Jim Blandy committed
299

Jim Blandy's avatar
Jim Blandy committed
300
  final = indirect_function (macro);
301
  if (!STRINGP (final) && !VECTORP (final))
302
    error ("Keyboard macros must be strings or vectors");
Jim Blandy's avatar
Jim Blandy committed
303

304 305 306
  tem = Fcons (Vexecuting_macro,
	       Fcons (make_number (executing_macro_index),
		      real_this_command));
Jim Blandy's avatar
Jim Blandy committed
307 308 309 310 311 312
  record_unwind_protect (pop_kbd_macro, tem);

  GCPRO1 (final);
  do
    {
      Vexecuting_macro = final;
313
      executing_macro = final;
Jim Blandy's avatar
Jim Blandy committed
314 315
      executing_macro_index = 0;

316
      current_kboard->Vprefix_arg = Qnil;
Jim Blandy's avatar
Jim Blandy committed
317
      command_loop_1 ();
318

319 320
      executing_macro_iterations = ++success_count;

321
      QUIT;
Jim Blandy's avatar
Jim Blandy committed
322
    }
323 324
  while (--repeat
	 && (STRINGP (Vexecuting_macro) || VECTORP (Vexecuting_macro)));
Jim Blandy's avatar
Jim Blandy committed
325

326 327
  executing_macro = Qnil;

328 329
  real_this_command = Vexecuting_macro;

Jim Blandy's avatar
Jim Blandy committed
330
  UNGCPRO;
331
  return unbind_to (pdlcount, Qnil);
Jim Blandy's avatar
Jim Blandy committed
332 333
}

334
void
Jim Blandy's avatar
Jim Blandy committed
335 336 337
init_macros ()
{
  Vexecuting_macro = Qnil;
338
  executing_macro = Qnil;
Jim Blandy's avatar
Jim Blandy committed
339 340
}

341
void
Jim Blandy's avatar
Jim Blandy committed
342 343 344 345
syms_of_macros ()
{
  Qexecute_kbd_macro = intern ("execute-kbd-macro");
  staticpro (&Qexecute_kbd_macro);
346 347
  Qkbd_macro_termination_hook = intern ("kbd-macro-termination-hook");
  staticpro (&Qkbd_macro_termination_hook);
Jim Blandy's avatar
Jim Blandy committed
348 349 350 351 352

  defsubr (&Sstart_kbd_macro);
  defsubr (&Send_kbd_macro);
  defsubr (&Scall_last_kbd_macro);
  defsubr (&Sexecute_kbd_macro);
353
  defsubr (&Scancel_kbd_macro_events);
354
  defsubr (&Sstore_kbd_macro_event);
Jim Blandy's avatar
Jim Blandy committed
355

Karl Heuer's avatar
Karl Heuer committed
356
  DEFVAR_KBOARD ("defining-kbd-macro", defining_kbd_macro,
Jim Blandy's avatar
Jim Blandy committed
357 358 359
    "Non-nil while a keyboard macro is being defined.  Don't set this!");

  DEFVAR_LISP ("executing-macro", &Vexecuting_macro,
360
    "Currently executing keyboard macro (string or vector); nil if none executing.");
Jim Blandy's avatar
Jim Blandy committed
361 362

  DEFVAR_LISP_NOPRO ("executing-kbd-macro", &Vexecuting_macro,
363
    "Currently executing keyboard macro (string or vector); nil if none executing.");
Jim Blandy's avatar
Jim Blandy committed
364

Karl Heuer's avatar
Karl Heuer committed
365
  DEFVAR_KBOARD ("last-kbd-macro", Vlast_kbd_macro,
366
    "Last kbd macro defined, as a string or vector; nil if none defined.");
Jim Blandy's avatar
Jim Blandy committed
367 368
}

369
void
Jim Blandy's avatar
Jim Blandy committed
370 371 372 373 374 375
keys_of_macros ()
{
  initial_define_key (control_x_map, ('e'), "call-last-kbd-macro");
  initial_define_key (control_x_map, ('('), "start-kbd-macro");
  initial_define_key (control_x_map, (')'), "end-kbd-macro");
}