macros.c 7.96 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 18 19 20
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
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */


21
#include <config.h>
Jim Blandy's avatar
Jim Blandy committed
22 23 24 25 26
#include "lisp.h"
#include "macros.h"
#include "commands.h"
#include "buffer.h"
#include "window.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
27
#include "keyboard.h"
Jim Blandy's avatar
Jim Blandy committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

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
46
  if (!NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
47 48
    error ("Already defining kbd macro");

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

Jim Blandy's avatar
Jim Blandy committed
90
  if (NILP (arg))
91
    XSETFASTINT (arg, 1);
Jim Blandy's avatar
Jim Blandy committed
92 93 94
  else
    CHECK_NUMBER (arg, 0);

Karl Heuer's avatar
Karl Heuer committed
95
  if (!NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
96
    {
Karl Heuer's avatar
Karl Heuer committed
97
      current_kboard->defining_kbd_macro = Qnil;
Jim Blandy's avatar
Jim Blandy committed
98
      update_mode_lines++;
Karl Heuer's avatar
Karl Heuer committed
99 100 101 102
      current_kboard->Vlast_kbd_macro
	= make_event_array ((current_kboard->kbd_macro_end
			     - current_kboard->kbd_macro_buffer),
			    current_kboard->kbd_macro_buffer);
Jim Blandy's avatar
Jim Blandy committed
103 104 105 106
      message("Keyboard macro defined");
    }

  if (XFASTINT (arg) == 0)
Karl Heuer's avatar
Karl Heuer committed
107
    Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, arg);
Jim Blandy's avatar
Jim Blandy committed
108 109
  else
    {
110 111
      XSETINT (arg, XINT (arg)-1);
      if (XINT (arg) > 0)
Karl Heuer's avatar
Karl Heuer committed
112
	Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, arg);
Jim Blandy's avatar
Jim Blandy committed
113 114 115 116 117 118 119 120 121
    }
  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
122
  if (!NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
123
    {
Karl Heuer's avatar
Karl Heuer committed
124 125 126
      if ((current_kboard->kbd_macro_ptr
	   - current_kboard->kbd_macro_buffer)
	  == current_kboard->kbd_macro_bufsize)
Jim Blandy's avatar
Jim Blandy committed
127
	{
128
	  register Lisp_Object *new;
Karl Heuer's avatar
Karl Heuer committed
129 130 131
	  current_kboard->kbd_macro_bufsize *= 2;
	  new = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
					 (current_kboard->kbd_macro_bufsize
132
					  * sizeof (Lisp_Object)));
Karl Heuer's avatar
Karl Heuer committed
133 134 135 136 137
	  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
138
	}
Karl Heuer's avatar
Karl Heuer committed
139
      *current_kboard->kbd_macro_ptr++ = c;
Jim Blandy's avatar
Jim Blandy committed
140 141 142 143 144 145 146 147
    }
}

/* 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
148
  current_kboard->kbd_macro_end = current_kboard->kbd_macro_ptr;
Jim Blandy's avatar
Jim Blandy committed
149
}
150 151 152 153 154 155 156 157

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;
}
Jim Blandy's avatar
Jim Blandy committed
158 159 160 161 162 163 164 165 166 167 168 169

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
170
  if (! NILP (current_kboard->defining_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
171
    error ("Can't execute anonymous macro while defining one");
Karl Heuer's avatar
Karl Heuer committed
172
  else if (NILP (current_kboard->Vlast_kbd_macro))
Jim Blandy's avatar
Jim Blandy committed
173 174
    error ("No kbd macro has been defined");
  else
Karl Heuer's avatar
Karl Heuer committed
175
    Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, prefix);
Jim Blandy's avatar
Jim Blandy committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  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.")
  (macro, prefixarg)
     Lisp_Object macro, prefixarg;
{
  Lisp_Object final;
  Lisp_Object tem;
  int count = specpdl_ptr - specpdl;
  int repeat = 1;
  struct gcpro gcpro1;

Jim Blandy's avatar
Jim Blandy committed
205
  if (!NILP (prefixarg))
Jim Blandy's avatar
Jim Blandy committed
206 207 208
    prefixarg = Fprefix_numeric_value (prefixarg),
    repeat = XINT (prefixarg);

Jim Blandy's avatar
Jim Blandy committed
209
  final = indirect_function (macro);
210
  if (!STRINGP (final) && !VECTORP (final))
Jim Blandy's avatar
Jim Blandy committed
211 212
    error ("Keyboard macros must be strings or vectors.");

213
  XSETFASTINT (tem, executing_macro_index);
Jim Blandy's avatar
Jim Blandy committed
214 215 216 217 218 219 220 221 222
  tem = Fcons (Vexecuting_macro, tem);
  record_unwind_protect (pop_kbd_macro, tem);

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

223
      current_kboard->Vprefix_arg = Qnil;
Jim Blandy's avatar
Jim Blandy committed
224
      command_loop_1 ();
225 226

      QUIT;
Jim Blandy's avatar
Jim Blandy committed
227
    }
228 229
  while (--repeat
	 && (STRINGP (Vexecuting_macro) || VECTORP (Vexecuting_macro)));
Jim Blandy's avatar
Jim Blandy committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

  UNGCPRO;
  return unbind_to (count, Qnil);
}

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);
249
  defsubr (&Scancel_kbd_macro_events);
Jim Blandy's avatar
Jim Blandy committed
250

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

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

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

Karl Heuer's avatar
Karl Heuer committed
260
  DEFVAR_KBOARD ("last-kbd-macro", Vlast_kbd_macro,
261
    "Last kbd macro defined, as a string or vector; nil if none defined.");
Jim Blandy's avatar
Jim Blandy committed
262 263 264 265 266 267 268 269
}

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