comparison src/callint.c @ 407:a82d2d892c89

Initial revision
author Michael I. Bushnell <mib@gnu.org>
date Sun, 25 Aug 1991 01:14:32 +0000
parents
children 8b54ee2c82d6
comparison
equal deleted inserted replaced
406:bd0533ed9b5a 407:a82d2d892c89
1 /* Call a Lisp function interactively.
2 Copyright (C) 1985, 1986 Free Software Foundation, Inc.
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
8 the Free Software Foundation; either version 1, or (at your option)
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
21 #include "config.h"
22 #include "lisp.h"
23 #include "buffer.h"
24 #include "commands.h"
25 #include "window.h"
26 #include "mocklisp.h"
27
28 extern char *index ();
29
30 Lisp_Object Vprefix_arg, Vcurrent_prefix_arg, Qminus;
31 Lisp_Object Qcall_interactively;
32 Lisp_Object Vcommand_history;
33
34 Lisp_Object Vcommand_debug_status, Qcommand_debug_status;
35
36 /* This comment supplies the doc string for interactive,
37 for make-docfile to see. We cannot put this in the real DEFUN
38 due to limits in the Unix cpp.
39
40 DEFUN ("interactive", Ffoo, Sfoo, 0, 0, 0,
41 "Specify a way of parsing arguments for interactive use of a function.\n\
42 For example, write\n\
43 (defun foo (arg) \"Doc string\" (interactive \"p\") ...use arg...)\n\
44 to make ARG be the prefix argument when `foo' is called as a command.\n\
45 The \"call\" to `interactive' is actually a declaration rather than a function;\n\
46 it tells `call-interactively' how to read arguments\n\
47 to pass to the function.\n\
48 When actually called, `interactive' just returns nil.\n\
49 \n\
50 The argument of `interactive' is usually a string containing a code letter\n\
51 followed by a prompt. (Some code letters do not use I/O to get\n\
52 the argument and do not need prompts.) To prompt for multiple arguments,\n\
53 give a code letter, its prompt, a newline, and another code letter, etc.\n\
54 Prompts are passed to format, and may use % escapes to print the\n\
55 arguments that have already been read.\n\
56 If the argument is not a string, it is evaluated to get a list of\n\
57 arguments to pass to the function.\n\
58 Just `(interactive)' means pass no args when calling interactively.\n\
59 \nCode letters available are:\n\
60 a -- Function name: symbol with a function definition.\n\
61 b -- Name of existing buffer.\n\
62 B -- Name of buffer, possibly nonexistent.\n\
63 c -- Character.\n\
64 C -- Command name: symbol with interactive function definition.\n\
65 d -- Value of point as number. Does not do I/O.\n\
66 D -- Directory name.\n\
67 e -- Last mouse event.\n\
68 f -- Existing file name.\n\
69 F -- Possibly nonexistent file name.\n\
70 k -- Key sequence (string).\n\
71 m -- Value of mark as number. Does not do I/O.\n\
72 n -- Number read using minibuffer.\n\
73 N -- Prefix arg converted to number, or if none, do like code `n'.\n\
74 p -- Prefix arg converted to number. Does not do I/O.\n\
75 P -- Prefix arg in raw form. Does not do I/O.\n\
76 r -- Region: point and mark as 2 numeric args, smallest first. Does no I/O.\n\
77 s -- Any string.\n\
78 S -- Any symbol.\n\
79 v -- Variable name: symbol that is user-variable-p.\n\
80 x -- Lisp expression read but not evaluated.\n\
81 X -- Lisp expression read and evaluated.\n\
82 In addition, if the string begins with `*'\n\
83 then an error is signaled if the buffer is read-only.\n\
84 This happens before reading any arguments.\n\
85 If the string begins with `@', then the window the mouse is over is selected\n\
86 before anything else is done. You may use both `@' and `*';\n\
87 they are processed in the order that they appear."
88 */
89
90 /* ARGSUSED */
91 DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
92 0 /* See immediately above */)
93 (args)
94 Lisp_Object args;
95 {
96 return Qnil;
97 }
98
99 /* Quotify EXP: if EXP is constant, return it.
100 If EXP is not constant, return (quote EXP). */
101 Lisp_Object
102 quotify_arg (exp)
103 register Lisp_Object exp;
104 {
105 if (XTYPE (exp) != Lisp_Int && XTYPE (exp) != Lisp_String
106 && !NULL (exp) && !EQ (exp, Qt))
107 return Fcons (Qquote, Fcons (exp, Qnil));
108
109 return exp;
110 }
111
112 /* Modify EXP by quotifying each element (except the first). */
113 Lisp_Object
114 quotify_args (exp)
115 Lisp_Object exp;
116 {
117 register Lisp_Object tail;
118 register struct Lisp_Cons *ptr;
119 for (tail = exp; CONSP (tail); tail = ptr->cdr)
120 {
121 ptr = XCONS (tail);
122 ptr->car = quotify_arg (ptr->car);
123 }
124 return exp;
125 }
126
127 char *callint_argfuns[]
128 = {"", "point", "mark", "region-beginning", "region-end"};
129
130 static void
131 check_mark ()
132 {
133 Lisp_Object tem = Fmarker_buffer (current_buffer->mark);
134 if (NULL (tem) || (XBUFFER (tem) != current_buffer))
135 error ("The mark is not set now");
136 }
137
138
139 DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 2, 0,
140 "Call FUNCTION, reading args according to its interactive calling specs.\n\
141 The function contains a specification of how to do the argument reading.\n\
142 In the case of user-defined functions, this is specified by placing a call\n\
143 to the function `interactive' at the top level of the function body.\n\
144 See `interactive'.\n\
145 \n\
146 Optional second arg RECORD-FLAG non-nil\n\
147 means unconditionally put this command in the command-history.\n\
148 Otherwise, this is done only if an arg is read using the minibuffer.")
149 (function, record)
150 Lisp_Object function, record;
151 {
152 Lisp_Object *args, *visargs;
153 unsigned char **argstrings;
154 Lisp_Object fun;
155 Lisp_Object funcar;
156 Lisp_Object specs;
157 Lisp_Object teml;
158
159 Lisp_Object prefix_arg;
160 unsigned char *string;
161 unsigned char *tem;
162 int *varies;
163 register int i, j;
164 int count, foo;
165 char prompt[100];
166 char prompt1[100];
167 char *tem1;
168 int arg_from_tty = 0;
169 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
170
171 /* Save this now, since use ofminibuffer will clobber it. */
172 prefix_arg = Vcurrent_prefix_arg;
173
174 retry:
175
176 fun = function;
177 while (XTYPE (fun) == Lisp_Symbol && !EQ (fun, Qunbound)) fun = XSYMBOL (fun)->function;
178
179 specs = Qnil;
180 string = 0;
181
182 /* Decode the kind of function. Either handle it and return,
183 or go to `lose' if not interactive, or go to `retry'
184 to specify a different function, or set either STRING or SPECS. */
185
186 if (XTYPE (fun) == Lisp_Subr)
187 {
188 string = (unsigned char *) XSUBR (fun)->prompt;
189 if (!string)
190 {
191 lose:
192 function = wrong_type_argument (Qcommandp, function, 0);
193 goto retry;
194 }
195 if ((int) string == 1)
196 /* Let SPECS (which is nil) be used as the args. */
197 string = 0;
198 }
199 else if (XTYPE (fun) == Lisp_Compiled)
200 {
201 if (XVECTOR (fun)->size <= COMPILED_INTERACTIVE)
202 goto lose;
203 specs = XVECTOR (fun)->contents[COMPILED_INTERACTIVE];
204 }
205 else if (!CONSP (fun))
206 goto lose;
207 else if (funcar = Fcar (fun), EQ (funcar, Qautoload))
208 {
209 GCPRO2 (function, prefix_arg);
210 do_autoload (fun, function);
211 UNGCPRO;
212 goto retry;
213 }
214 else if (EQ (funcar, Qlambda))
215 {
216 specs = Fassq (Qinteractive, Fcdr (Fcdr (fun)));
217 if (NULL (specs))
218 goto lose;
219 specs = Fcar (Fcdr (specs));
220 }
221 else if (EQ (funcar, Qmocklisp))
222 return ml_apply (fun, Qinteractive);
223 else
224 goto lose;
225
226 if (XTYPE (specs) == Lisp_String)
227 string = XSTRING (specs)->data;
228 else if (string == 0)
229 {
230 i = num_input_chars;
231 specs = Feval (specs);
232 if (i != num_input_chars || !NULL (record))
233 Vcommand_history
234 = Fcons (Fcons (function, quotify_args (Fcopy_sequence (specs))),
235 Vcommand_history);
236 return apply1 (function, specs);
237 }
238
239 /* Here if function specifies a string to control parsing the defaults */
240
241 /* Handle special starting chars `*' and `@'. */
242 while (1)
243 {
244 if (*string == '*')
245 {
246 string++;
247 if (!NULL (current_buffer->read_only))
248 Fbarf_if_buffer_read_only ();
249 }
250 else if (*string == '@')
251 {
252 string++;
253 if (!NULL (Vmouse_window))
254 Fselect_window (Vmouse_window);
255 }
256 else break;
257 }
258
259 /* Count the number of arguments the interactive spec would have
260 us give to the function. */
261 tem = string;
262 for (j = 0; *tem; j++)
263 {
264 /* 'r' specifications ("point and mark as 2 numeric args")
265 produce *two* arguments. */
266 if (*tem == 'r') j++;
267 tem = (unsigned char *) index (tem, '\n');
268 if (tem)
269 tem++;
270 else
271 tem = (unsigned char *) "";
272 }
273 count = j;
274
275 args = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
276 visargs = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
277 argstrings = (unsigned char **) alloca ((count + 1) * sizeof (char *));
278 varies = (int *) alloca ((count + 1) * sizeof (int));
279
280 for (i = 0; i < (count + 1); i++)
281 {
282 args[i] = Qnil;
283 visargs[i] = Qnil;
284 varies[i] = 0;
285 }
286
287 GCPRO4 (prefix_arg, function, *args, *visargs);
288 gcpro3.nvars = (count + 1);
289 gcpro4.nvars = (count + 1);
290
291 tem = string;
292 for (i = 1; *tem; i++)
293 {
294 strncpy (prompt1, tem + 1, sizeof prompt1 - 1);
295 prompt1[sizeof prompt1 - 1] = 0;
296 tem1 = index (prompt1, '\n');
297 if (tem1) *tem1 = 0;
298 /* Fill argstrings with a vector of C strings
299 corresponding to the Lisp strings in visargs. */
300 for (j = 1; j < i; j++)
301 argstrings[j]
302 = EQ (visargs[j], Qnil)
303 ? (unsigned char *) ""
304 : XSTRING (visargs[j])->data;
305
306 doprnt (prompt, sizeof prompt, prompt1, 0, j - 1, argstrings + 1);
307
308 switch (*tem)
309 {
310 case 'a': /* Symbol defined as a function */
311 visargs[i] = Fcompleting_read (build_string (prompt),
312 Vobarray, Qfboundp, Qt, Qnil, Qnil);
313 /* Passing args[i] directly stimulates compiler bug */
314 teml = visargs[i];
315 args[i] = Fintern (teml, Qnil);
316 break;
317
318 case 'b': /* Name of existing buffer */
319 args[i] = Fcurrent_buffer ();
320 if (EQ (selected_window, minibuf_window))
321 args[i] = Fother_buffer (args[i]);
322 args[i] = Fread_buffer (build_string (prompt), args[i], Qt);
323 break;
324
325 case 'B': /* Name of buffer, possibly nonexistent */
326 args[i] = Fread_buffer (build_string (prompt),
327 Fother_buffer (Fcurrent_buffer ()), Qnil);
328 break;
329
330 case 'c': /* Character */
331 message1 (prompt);
332 args[i] = Fread_char ();
333 /* Passing args[i] directly stimulates compiler bug */
334 teml = args[i];
335 visargs[i] = Fchar_to_string (teml);
336 break;
337
338 case 'C': /* Command: symbol with interactive function */
339 visargs[i] = Fcompleting_read (build_string (prompt),
340 Vobarray, Qcommandp, Qt, Qnil, Qnil);
341 /* Passing args[i] directly stimulates compiler bug */
342 teml = visargs[i];
343 args[i] = Fintern (teml, Qnil);
344 break;
345
346 case 'd': /* Value of point. Does not do I/O. */
347 XFASTINT (args[i]) = point;
348 /* visargs[i] = Qnil; */
349 varies[i] = 1;
350 break;
351
352 case 'e':
353 varies[i] = 1;
354 args[i] = Vmouse_event;
355 break;
356
357 case 'D': /* Directory name. */
358 args[i] = Fread_file_name (build_string (prompt), Qnil,
359 current_buffer->directory, Qlambda, Qnil);
360 break;
361
362 case 'f': /* Existing file name. */
363 args[i] = Fread_file_name (build_string (prompt),
364 Qnil, Qnil, Qlambda, Qnil);
365 break;
366
367 case 'F': /* Possibly nonexistent file name. */
368 args[i] = Fread_file_name (build_string (prompt),
369 Qnil, Qnil, Qnil, Qnil);
370 break;
371
372 case 'k': /* Key sequence (string) */
373 args[i] = Fread_key_sequence (build_string (prompt));
374 teml = args[i];
375 visargs[i] = Fkey_description (teml);
376 break;
377
378 case 'm': /* Value of mark. Does not do I/O. */
379 check_mark ();
380 /* visargs[i] = Qnil; */
381 XFASTINT (args[i]) = marker_position (current_buffer->mark);
382 varies[i] = 2;
383 break;
384
385 case 'N': /* Prefix arg, else number from minibuffer */
386 if (!NULL (prefix_arg))
387 goto have_prefix_arg;
388 case 'n': /* Read number from minibuffer. */
389 do
390 args[i] = Fread_minibuffer (build_string (prompt), Qnil);
391 #ifdef LISP_FLOAT_TYPE
392 while (XTYPE (args[i]) != Lisp_Int
393 && XTYPE (args[i]) != Lisp_Float);
394 #else
395 while (XTYPE (args[i]) != Lisp_Int);
396 #endif
397 visargs[i] = last_minibuf_string;
398 break;
399
400 case 'P': /* Prefix arg in raw form. Does no I/O. */
401 have_prefix_arg:
402 args[i] = prefix_arg;
403 /* visargs[i] = Qnil; */
404 varies[i] = -1;
405 break;
406
407 case 'p': /* Prefix arg converted to number. No I/O. */
408 args[i] = Fprefix_numeric_value (prefix_arg);
409 /* visargs[i] = Qnil; */
410 varies[i] = -1;
411 break;
412
413 case 'r': /* Region, point and mark as 2 args. */
414 check_mark ();
415 /* visargs[i+1] = Qnil; */
416 foo = marker_position (current_buffer->mark);
417 /* visargs[i] = Qnil; */
418 XFASTINT (args[i]) = point < foo ? point : foo;
419 varies[i] = 3;
420 XFASTINT (args[++i]) = point > foo ? point : foo;
421 varies[i] = 4;
422 break;
423
424 case 's': /* String read via minibuffer. */
425 args[i] = Fread_string (build_string (prompt), Qnil);
426 break;
427
428 case 'S': /* Any symbol. */
429 visargs[i] = read_minibuf (Vminibuffer_local_ns_map,
430 Qnil,
431 build_string (prompt),
432 0);
433 /* Passing args[i] directly stimulates compiler bug */
434 teml = visargs[i];
435 args[i] = Fintern (teml, Qnil);
436 break;
437
438 case 'v': /* Variable name: symbol that is
439 user-variable-p. */
440 args[i] = Fread_variable (build_string (prompt));
441 visargs[i] = last_minibuf_string;
442 break;
443
444 case 'x': /* Lisp expression read but not evaluated */
445 args[i] = Fread_minibuffer (build_string (prompt), Qnil);
446 visargs[i] = last_minibuf_string;
447 break;
448
449 case 'X': /* Lisp expression read and evaluated */
450 args[i] = Feval_minibuffer (build_string (prompt), Qnil);
451 visargs[i] = last_minibuf_string;
452 break;
453
454 default:
455 error ("Invalid control letter \"%c\" (%03o) in interactive calling string",
456 *tem, *tem);
457 }
458
459 if (varies[i] == 0)
460 arg_from_tty = 1;
461
462 if (NULL (visargs[i]) && XTYPE (args[i]) == Lisp_String)
463 visargs[i] = args[i];
464
465 tem = (unsigned char *) index (tem, '\n');
466 if (tem) tem++;
467 else tem = (unsigned char *) "";
468 }
469
470 QUIT;
471
472 args[0] = function;
473
474 if (arg_from_tty || !NULL (record))
475 {
476 visargs[0] = function;
477 for (i = 1; i < count + 1; i++ if (varies[i] > 0)
478 visargs[i] = Fcons (intern (callint_argfuns[varies[i]]), Qnil);
479 else
480 visargs[i] = quotify_arg (args[i]);
481 Vcommand_history = Fcons (Flist (count + 1, visargs),
482 Vcommand_history);
483 }
484
485 {
486 Lisp_Object val;
487 int speccount = specpdl_ptr - specpdl;
488 specbind (Qcommand_debug_status, Qnil);
489
490 val = Ffuncall (count + 1, args);
491 UNGCPRO;
492 return unbind_to (speccount, val);
493 }
494 }
495
496 DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value,
497 1, 1, 0,
498 "Return numeric meaning of raw prefix argument ARG.\n\
499 A raw prefix argument is what you get from `(interactive \"P\")'.\n\
500 Its numeric meaning is what you would get from `(interactive \"p\")'.")
501 (raw)
502 Lisp_Object raw;
503 {
504 Lisp_Object val;
505
506 /* Tag val as an integer, so the rest of the assignments
507 may use XSETINT. */
508 XFASTINT (val) = 0;
509
510 if (NULL (raw))
511 XFASTINT (val) = 1;
512 else if (XTYPE (raw) == Lisp_Symbol)
513 XSETINT (val, -1);
514 else if (CONSP (raw))
515 XSETINT (val, XINT (XCONS (raw)->car));
516 else if (XTYPE (raw) == Lisp_Int)
517 val = raw;
518 else
519 XFASTINT (val) = 1;
520
521 return val;
522 }
523
524 syms_of_callint ()
525 {
526 Qminus = intern ("-");
527 staticpro (&Qminus);
528
529 Qcall_interactively = intern ("call-interactively");
530 staticpro (&Qcall_interactively);
531
532 Qcommand_debug_status = intern ("command-debug-status");
533 staticpro (&Qcommand_debug_status);
534
535 DEFVAR_LISP ("prefix-arg", &Vprefix_arg,
536 "The value of the prefix argument for the next editing command.\n\
537 It may be a number, or the symbol `-' for just a minus sign as arg,\n\
538 or a list whose car is a number for just one or more C-U's\n\
539 or nil if no argument has been specified.\n\
540 \n\
541 You cannot examine this variable to find the argument for this command\n\
542 since it has been set to nil by the time you can look.\n\
543 Instead, you should use the variable `current-prefix-arg', although\n\
544 normally commands can get this prefix argument with (interactive \"P\").");
545 Vprefix_arg = Qnil;
546
547 DEFVAR_LISP ("current-prefix-arg", &Vcurrent_prefix_arg,
548 "The value of the prefix argument for this editing command.\n\
549 It may be a number, or the symbol `-' for just a minus sign as arg,\n\
550 or a list whose car is a number for just one or more C-U's\n\
551 or nil if no argument has been specified.\n\
552 This is what `(interactive \"P\")' returns.");
553 Vcurrent_prefix_arg = Qnil;
554
555 DEFVAR_LISP ("command-history", &Vcommand_history,
556 "List of recent commands that read arguments from terminal.\n\
557 Each command is represented as a form to evaluate.");
558 Vcommand_history = Qnil;
559
560 DEFVAR_LISP ("command-debug-status", &Vcommand_debug_status,
561 "Debugging status of current interactive command.\n\
562 Bound each time `call-interactively' is called;\n\
563 may be set by the debugger as a reminder for itself.");
564 Vcommand_debug_status = Qnil;
565
566 defsubr (&Sinteractive);
567 defsubr (&Scall_interactively);
568 defsubr (&Sprefix_numeric_value);
569 }