macros.c 8.52 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Keyboard macros.
Jim Blandy's avatar
Jim Blandy committed
2
   Copyright (C) 1985, 1986, 1993 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

Lisp_Object Qexecute_kbd_macro;

Lisp_Object Vexecuting_macro;
int executing_macro_index;

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\
 This begins by re-executing that macro as if you typed it again.")
  (append)
     Lisp_Object append;
{
Karl Heuer's avatar
Karl Heuer committed
47
  if (!NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
48 49
    error ("Already defining kbd macro");

Karl Heuer's avatar
Karl Heuer committed
50
  if (!current_kboard->kbd_macro_buffer)
51
    {
Karl Heuer's avatar
Karl Heuer committed
52 53
      current_kboard->kbd_macro_bufsize = 30;
      current_kboard->kbd_macro_buffer
54
	= (Lisp_Object *)xmalloc (30 * sizeof (Lisp_Object));
55
    }
Jim Blandy's avatar
Jim Blandy committed
56
  update_mode_lines++;
Jim Blandy's avatar
Jim Blandy committed
57
  if (NILP (append))
Jim Blandy's avatar
Jim Blandy committed
58
    {
59 60 61 62
      if (current_kboard->kbd_macro_bufsize > 200)
	{
	  current_kboard->kbd_macro_bufsize = 30;
	  current_kboard->kbd_macro_buffer
63 64
	    = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
				       30 * sizeof (Lisp_Object));
65
	}
Karl Heuer's avatar
Karl Heuer committed
66 67
      current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer;
      current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer;
68
      message ("Defining kbd macro...");
Jim Blandy's avatar
Jim Blandy committed
69 70 71
    }
  else
    {
72
      message ("Appending to kbd macro...");
Karl Heuer's avatar
Karl Heuer committed
73 74
      current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_end;
      Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro,
75
			  make_number (1));
Jim Blandy's avatar
Jim Blandy committed
76
    }
Karl Heuer's avatar
Karl Heuer committed
77
  current_kboard->defining_kbd_macro = Qt;
Jim Blandy's avatar
Jim Blandy committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91
  
  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.")
92 93
  (repeat)
     Lisp_Object repeat;
Jim Blandy's avatar
Jim Blandy committed
94
{
Karl Heuer's avatar
Karl Heuer committed
95 96
  if (NILP (current_kboard->defining_kbd_macro))
    error ("Not defining kbd macro.");
Jim Blandy's avatar
Jim Blandy committed
97

98 99
  if (NILP (repeat))
    XSETFASTINT (repeat, 1);
Jim Blandy's avatar
Jim Blandy committed
100
  else
101
    CHECK_NUMBER (repeat, 0);
Jim Blandy's avatar
Jim Blandy committed
102

Karl Heuer's avatar
Karl Heuer committed
103
  if (!NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
104
    {
Karl Heuer's avatar
Karl Heuer committed
105
      current_kboard->defining_kbd_macro = Qnil;
Jim Blandy's avatar
Jim Blandy committed
106
      update_mode_lines++;
Karl Heuer's avatar
Karl Heuer committed
107 108 109 110
      current_kboard->Vlast_kbd_macro
	= make_event_array ((current_kboard->kbd_macro_end
			     - current_kboard->kbd_macro_buffer),
			    current_kboard->kbd_macro_buffer);
111
      message ("Keyboard macro defined");
Jim Blandy's avatar
Jim Blandy committed
112 113
    }

114 115
  if (XFASTINT (repeat) == 0)
    Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, repeat);
Jim Blandy's avatar
Jim Blandy committed
116 117
  else
    {
118 119 120
      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
121 122 123 124 125 126 127 128 129
    }
  return Qnil;
}

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

store_kbd_macro_char (c)
     Lisp_Object c;
{
Karl Heuer's avatar
Karl Heuer committed
130
  if (!NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
131
    {
Karl Heuer's avatar
Karl Heuer committed
132 133 134
      if ((current_kboard->kbd_macro_ptr
	   - current_kboard->kbd_macro_buffer)
	  == current_kboard->kbd_macro_bufsize)
Jim Blandy's avatar
Jim Blandy committed
135
	{
136
	  register Lisp_Object *new;
Karl Heuer's avatar
Karl Heuer committed
137 138 139
	  current_kboard->kbd_macro_bufsize *= 2;
	  new = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
					 (current_kboard->kbd_macro_bufsize
140
					  * sizeof (Lisp_Object)));
Karl Heuer's avatar
Karl Heuer committed
141 142 143 144 145
	  current_kboard->kbd_macro_ptr
	    += new - current_kboard->kbd_macro_buffer;
	  current_kboard->kbd_macro_end
	    += new - current_kboard->kbd_macro_buffer;
	  current_kboard->kbd_macro_buffer = new;
Jim Blandy's avatar
Jim Blandy committed
146
	}
Karl Heuer's avatar
Karl Heuer committed
147
      *current_kboard->kbd_macro_ptr++ = c;
Jim Blandy's avatar
Jim Blandy committed
148 149 150 151 152 153 154 155
    }
}

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

finalize_kbd_macro_chars ()
{
Karl Heuer's avatar
Karl Heuer committed
156
  current_kboard->kbd_macro_end = current_kboard->kbd_macro_ptr;
Jim Blandy's avatar
Jim Blandy committed
157
}
158 159 160 161 162 163 164 165

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;
}
166 167 168 169 170 171 172 173 174 175

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
176 177 178 179 180 181 182 183 184 185 186 187

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;
{
Karl Heuer's avatar
Karl Heuer committed
188
  if (! NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
189
    error ("Can't execute anonymous macro while defining one");
Karl Heuer's avatar
Karl Heuer committed
190
  else if (NILP (current_kboard->Vlast_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
191 192
    error ("No kbd macro has been defined");
  else
Karl Heuer's avatar
Karl Heuer committed
193
    Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, prefix);
Jim Blandy's avatar
Jim Blandy committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
  return Qnil;
}

/* Restore Vexecuting_macro and executing_macro_index - called when
   the unwind-protect in Fexecute_kbd_macro gets invoked.  */
static Lisp_Object
pop_kbd_macro (info)
     Lisp_Object info;
{
  Lisp_Object tem;
  Vexecuting_macro = Fcar (info);
  tem = Fcdr (info);
  executing_macro_index = XINT (tem);
  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.")
214 215
  (macro, count)
     Lisp_Object macro, count;
Jim Blandy's avatar
Jim Blandy committed
216 217 218
{
  Lisp_Object final;
  Lisp_Object tem;
219
  int pdlcount = specpdl_ptr - specpdl;
Jim Blandy's avatar
Jim Blandy committed
220 221 222
  int repeat = 1;
  struct gcpro gcpro1;

223 224 225 226 227
  if (!NILP (count))
    {
      count = Fprefix_numeric_value (count);
      repeat = XINT (count);
    }
Jim Blandy's avatar
Jim Blandy committed
228

Jim Blandy's avatar
Jim Blandy committed
229
  final = indirect_function (macro);
230
  if (!STRINGP (final) && !VECTORP (final))
Jim Blandy's avatar
Jim Blandy committed
231 232
    error ("Keyboard macros must be strings or vectors.");

233
  XSETFASTINT (tem, executing_macro_index);
Jim Blandy's avatar
Jim Blandy committed
234 235 236 237 238 239 240 241 242
  tem = Fcons (Vexecuting_macro, tem);
  record_unwind_protect (pop_kbd_macro, tem);

  GCPRO1 (final);
  do
    {
      Vexecuting_macro = final;
      executing_macro_index = 0;

243
      current_kboard->Vprefix_arg = Qnil;
Jim Blandy's avatar
Jim Blandy committed
244
      command_loop_1 ();
245 246

      QUIT;
Jim Blandy's avatar
Jim Blandy committed
247
    }
248 249
  while (--repeat
	 && (STRINGP (Vexecuting_macro) || VECTORP (Vexecuting_macro)));
Jim Blandy's avatar
Jim Blandy committed
250 251

  UNGCPRO;
252
  return unbind_to (pdlcount, Qnil);
Jim Blandy's avatar
Jim Blandy committed
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
}

init_macros ()
{
  Vexecuting_macro = Qnil;
}

syms_of_macros ()
{
  Qexecute_kbd_macro = intern ("execute-kbd-macro");
  staticpro (&Qexecute_kbd_macro);

  defsubr (&Sstart_kbd_macro);
  defsubr (&Send_kbd_macro);
  defsubr (&Scall_last_kbd_macro);
  defsubr (&Sexecute_kbd_macro);
269
  defsubr (&Scancel_kbd_macro_events);
270
  defsubr (&Sstore_kbd_macro_event);
Jim Blandy's avatar
Jim Blandy committed
271

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

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

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

Karl Heuer's avatar
Karl Heuer committed
281
  DEFVAR_KBOARD ("last-kbd-macro", Vlast_kbd_macro,
282
    "Last kbd macro defined, as a string or vector; nil if none defined.");
Jim Blandy's avatar
Jim Blandy committed
283 284 285 286 287 288 289 290
}

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");
}