|
|
1.1 root 1: /* Call a Lisp function interactively.
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 "buffer.h"
25: #include "commands.h"
26: #include "window.h"
27:
28: extern struct Lisp_Vector *CurrentGlobalMap;
29:
30: extern int num_input_chars;
31:
32: Lisp_Object Vprefix_arg, Vcurrent_prefix_arg, Qminus;
33: Lisp_Object Qcall_interactively;
34: Lisp_Object Vcommand_history;
35:
36: extern Lisp_Object ml_apply ();
37: extern Lisp_Object Fread_buffer (), Fread_key_sequence (), Fread_file_name ();
38:
39: /* ARGSUSED */
40: DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
41: 0 /* See auxdoc.c */)
42: (args)
43: Lisp_Object args;
44: {
45: return Qnil;
46: }
47:
48: /* Quotify EXP: if EXP is constant, return it.
49: If EXP is not constant, return (quote EXP). */
50: Lisp_Object
51: quotify_arg (exp)
52: register Lisp_Object exp;
53: {
54: if (XTYPE (exp) != Lisp_Int && XTYPE (exp) != Lisp_String
55: && !NULL (exp) && !EQ (exp, Qt))
56: return Fcons (Qquote, Fcons (exp, Qnil));
57:
58: return exp;
59: }
60:
61: /* Modify EXP by quotifying each element (except the first). */
62: Lisp_Object
63: quotify_args (exp)
64: Lisp_Object exp;
65: {
66: register Lisp_Object tail;
67: register struct Lisp_Cons *ptr;
68: for (tail = exp; LISTP (tail); tail = ptr->cdr)
69: {
70: ptr = XCONS (tail);
71: ptr->car = quotify_arg (ptr->car);
72: }
73: return exp;
74: }
75:
76: char *callint_argfuns[]
77: = {"", "point", "mark", "region-beginning", "region-end"};
78:
79: #define argfuns callint_argfuns
80:
81: DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 2, 0,
82: "Call FUNCTION, reading args from the terminal,\n\
83: if the interactive calling specs of FUNCTION request one.\n\
84: \n\
85: The function contains a specification of how to do the argument reading.\n\
86: In the case of user-defined functions, this is specified by placing a call to\n\
87: the function interactive at the top level of the function body. See interactive.")
88: (function, record)
89: Lisp_Object function, record;
90: {
91: Lisp_Object *args, *visargs;
92: unsigned char **argstrings;
93: Lisp_Object fun;
94: Lisp_Object funcar;
95: Lisp_Object specs;
96: Lisp_Object teml;
97:
98: Lisp_Object prefix_arg;
99: unsigned char *string;
100: unsigned char *tem;
101: int *varies;
102: register int i, j;
103: int count, foo;
104: char prompt[100];
105: char prompt1[100];
106: char *tem1;
107: int arg_from_tty = 0;
108: struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
109: extern char *index ();
110:
111: /* Save this now, since use ofminibuffer will clobber it. */
112: prefix_arg = Vcurrent_prefix_arg;
113:
114: retry:
115:
116: fun = function;
117: while (XTYPE (fun) == Lisp_Symbol && !EQ (fun, Qunbound)) fun = XSYMBOL (fun)->function;
118:
119: if (XTYPE (fun) == Lisp_Subr)
120: {
121: string = (unsigned char *) XSUBR (fun)->prompt;
122: if (!string)
123: {
124: lose:
125: function = wrong_type_argument (Qcommandp, function, 0);
126: goto retry;
127: }
128: else if ((int) string == 1)
129: return Fapply (function, Qnil);
130: }
131: else if (!LISTP (fun))
132: goto lose;
133: else if (funcar = Fcar (fun), EQ (funcar, Qautoload))
134: {
135: GCPRO2 (function, prefix_arg);
136: do_autoload (fun, function);
137: UNGCPRO;
138: goto retry;
139: }
140: else if (EQ (funcar, Qlambda))
141: {
142: specs = Fassq (Qinteractive, Fcdr (Fcdr (fun)));
143: if (NULL (specs))
144: goto lose;
145: specs = Fcar (Fcdr (specs));
146: if (XTYPE (specs) == Lisp_String)
147: string = XSTRING (specs)->data;
148: else
149: {
150: i = num_input_chars;
151: specs = Feval (specs);
152: if (i != num_input_chars || !NULL (record))
153: Vcommand_history
154: = Fcons (Fcons (function, quotify_args (Fcopy_sequence (specs))),
155: Vcommand_history);
156: return Fapply (function, specs);
157: }
158: }
159: else if (EQ (funcar, Qmocklisp))
160: return ml_apply (fun, Qinteractive);
161: else
162: goto lose;
163:
164: /* Here if function specifies a string to control parsing the defaults */
165:
166: /* First character '*' means barf if buffer read-only */
167: if (*string == '*')
168: { string++;
169: if (!NULL (bf_cur->read_only))
170: Fbarf_if_buffer_read_only ();
171: }
172:
173: tem = string;
174: for (j = 0; *tem; j++)
175: {
176: if (*tem == 'r') j++;
177: tem = (unsigned char *) index (tem, '\n');
178: if (tem) tem++;
179: else tem = (unsigned char *) "";
180: }
181: count = j;
182:
183: args = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
184: visargs = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
185: argstrings = (unsigned char **) alloca ((count + 1) * sizeof (char *));
186: varies = (int *) alloca ((count + 1) * sizeof (int));
187:
188: for (i = 0; i < (count + 1); i++)
189: {
190: args[i] = Qnil;
191: visargs[i] = Qnil;
192: varies[i] = 0;
193: }
194:
195: GCPRO4 (prefix_arg, function, *args, *visargs);
196: gcpro3.nvars = (count + 1);
197: gcpro4.nvars = (count + 1);
198:
199: tem = string;
200: for (i = 1; *tem; i++)
201: {
202: strncpy (prompt1, tem + 1, sizeof prompt1 - 1);
203: prompt1[sizeof prompt1 - 1] = 0;
204: tem1 = index (prompt1, '\n');
205: if (tem1) *tem1 = 0;
206: for (j = 1; j < i; j++)
207: argstrings[j] = XSTRING (visargs[j])->data;
208:
209: doprnt (prompt, sizeof prompt, prompt1, argstrings + 1);
210:
211: switch (*tem)
212: {
213: case 'a': /* Symbol defined as a function */
214: visargs[i] = Fcompleting_read (build_string (prompt),
215: Vobarray, Qfboundp, Qt, Qnil);
216: /* Passing args[i] directly stimulates compiler bug */
217: teml = visargs[i];
218: args[i] = Fintern (teml, Qnil);
219: break;
220:
221: case 'b': /* Name of existing buffer */
222: args[i] = Fcurrent_buffer ();
223: if (EQ (selected_window, minibuf_window))
224: args[i] = Fother_buffer (args[i]);
225: args[i] = Fread_buffer (build_string (prompt), args[i], Qt);
226: break;
227:
228: case 'B': /* Name of buffer, possibly nonexistent */
229: args[i] = Fread_buffer (build_string (prompt),
230: Fother_buffer (Fcurrent_buffer ()), Qnil);
231: break;
232:
233: case 'c': /* Character */
234: message1 (prompt);
235: args[i] = Fread_char ();
236: /* Passing args[i] directly stimulates compiler bug */
237: teml = args[i];
238: visargs[i] = Fchar_to_string (teml);
239: break;
240:
241: case 'C': /* Command: symbol with interactive function */
242: visargs[i] = Fcompleting_read (build_string (prompt),
243: Vobarray, Qcommandp, Qt, Qnil);
244: /* Passing args[i] directly stimulates compiler bug */
245: teml = visargs[i];
246: args[i] = Fintern (teml, Qnil);
247: break;
248:
249: case 'd': /* Value of point. Does not do I/O. */
250: XFASTINT (args[i]) = point;
251: visargs[i] = build_string ("point");
252: varies[i] = 1;
253: break;
254:
255: case 'D': /* Directory name. */
256: args[i] = Fread_file_name (build_string (prompt), Qnil,
257: bf_cur->directory, Qlambda);
258: break;
259:
260: case 'f': /* Existing file name. */
261: args[i] = Fread_file_name (build_string (prompt),
262: Qnil, Qnil, Qlambda);
263: break;
264:
265: case 'F': /* Possibly nonexistent file name. */
266: args[i] = Fread_file_name (build_string (prompt),
267: Qnil, Qnil, Qnil);
268: break;
269:
270: case 'k': /* Key sequence (string) */
271: args[i] = Fread_key_sequence (build_string (prompt));
272: teml = args[i];
273: visargs[i] = Fkey_description (teml);
274: break;
275:
276: case 'm': /* Value of mark. Does not do I/O. */
277: if (NULL (bf_cur->mark))
278: error ("The mark is not set now");
279: visargs[i] = build_string ("the mark");
280: XFASTINT (args[i]) = marker_position (bf_cur->mark);
281: varies[i] = 2;
282: break;
283:
284: case 'n': /* Read number from minibuffer. */
285: do
286: args[i] = Fread_minibuffer (build_string (prompt), Qnil);
287: while (XTYPE (args[i]) != Lisp_Int);
288: visargs[i] = last_minibuf_string;
289: break;
290:
291: case 'P': /* Prefix arg in raw form. Does no I/O. */
292: args[i] = prefix_arg;
293: XFASTINT (visargs[i]) = (int) "";
294: varies[i] = -1;
295: break;
296:
297: case 'p': /* Prefix arg converted to number. No I/O. */
298: args[i] = Fprefix_numeric_value (prefix_arg);
299: XFASTINT (visargs[i]) = (int) "";
300: varies[i] = -1;
301: break;
302:
303: case 'r': /* Region, point and mark as 2 args. */
304: if (NULL (bf_cur->mark))
305: error ("The mark is not set now");
306: foo = marker_position (bf_cur->mark);
307: visargs[i] = build_string ("point");
308: XFASTINT (args[i]) = point < foo ? point : foo;
309: varies[i] = 3;
310: visargs[++i] = build_string ("the mark");
311: XFASTINT (args[i]) = point > foo ? point : foo;
312: varies[i] = 4;
313: break;
314:
315: case 's': /* String read via minibuffer. */
316: args[i] = Fread_string (build_string (prompt), Qnil);
317: break;
318:
319: case 'S': /* Any symbol. */
320: visargs[i] = read_minibuf_string (Vminibuffer_local_ns_map,
321: Qnil,
322: build_string (prompt));
323: /* Passing args[i] directly stimulates compiler bug */
324: teml = visargs[i];
325: args[i] = Fintern (teml, Qnil);
326: break;
327:
328: case 'v': /* Variable name: symbol that is
329: user-variable-p. */
330: args[i] = Fread_variable (build_string (prompt));
331: visargs[i] = last_minibuf_string;
332: break;
333:
334: case 'x': /* Lisp expression read but not evaluated */
335: args[i] = Fread_minibuffer (build_string (prompt), Qnil);
336: visargs[i] = last_minibuf_string;
337: break;
338:
339: case 'X': /* Lisp expression read and evaluated */
340: args[i] = Feval_minibuffer (build_string (prompt), Qnil);
341: visargs[i] = last_minibuf_string;
342: break;
343:
344: default:
345: error ("Invalid control letter in interactive calling string");
346: }
347:
348: if (varies[i] == 0)
349: arg_from_tty = 1;
350:
351: if (NULL (visargs[i]))
352: visargs[i] = args[i];
353:
354: tem = (unsigned char *) index (tem, '\n');
355: if (tem) tem++;
356: else tem = (unsigned char *) "";
357: }
358:
359: UNGCPRO;
360:
361: QUIT;
362:
363: args[0] = function;
364:
365: if (arg_from_tty || !NULL (record))
366: {
367: visargs[0] = function;
368: for (i = 1; i < count + 1; i++)
369: if (varies[i] > 0)
370: visargs[i] = Fcons (intern (argfuns[varies[i]]), Qnil);
371: else
372: visargs[i] = quotify_arg (args[i]);
373: Vcommand_history = Fcons (Flist (count + 1, visargs),
374: Vcommand_history);
375: }
376:
377: return Ffuncall (count + 1, args);
378: }
379:
380: DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value,
381: 1, 1, 0,
382: "Return numeric meaning of raw prefix argument.\n\
383: A raw prefix argument is what you get from (interactive \"P\").")
384: (raw)
385: Lisp_Object raw;
386: {
387: Lisp_Object val;
388:
389: if (NULL (raw))
390: XFASTINT (val) = 1;
391: else if (XTYPE (raw) == Lisp_Symbol)
392: {
393: XFASTINT (val) = 0;
394: XSETINT (val, -1);
395: }
396: else if (LISTP (raw))
397: val = XCONS (raw)->car;
398: else if (XTYPE (raw) == Lisp_Int)
399: val = raw;
400: else
401: XFASTINT (val) = 1;
402:
403: return val;
404: }
405:
406: syms_of_callint ()
407: {
408: Qminus = intern ("-");
409: staticpro (&Qminus);
410:
411: Qcall_interactively = intern ("call-interactively");
412: staticpro (&Qcall_interactively);
413:
414: DefLispVar ("prefix-arg", &Vprefix_arg,
415: "The value of the prefix argument for the next editing command.\n\
416: It may be a number, or the symbol - for just a minus sign as arg,\n\
417: or a list whose car is a number for just one or more C-U's\n\
418: or nil if no argument has been specified.\n\
419: \n\
420: You cannot examine this variable to find the argument for this command\n\
421: since it has been set to nil by the time you can look.\n\
422: Instead, you should use the variable current-prefix-arg, although\n\
423: normally commands can get this prefix argument with (interactive \"P\").");
424:
425: DefLispVar ("current-prefix-arg", &Vcurrent_prefix_arg,
426: "The value of the prefix argument for this editing command.\n\
427: It may be a number, or the symbol - for just a minus sign as arg,\n\
428: or a list whose car is a number for just one or more C-U's\n\
429: or nil if no argument has been specified.\n\
430: This is what (interactive \"P\") returns.");
431:
432: DefLispVar ("command-history", &Vcommand_history,
433: "List of recent commands that read arguments from terminal.\n\
434: Each command is represented as a form to evaluate.");
435: Vcommand_history = Qnil;
436:
437: defsubr (&Sinteractive);
438: defsubr (&Scall_interactively);
439: defsubr (&Sprefix_numeric_value);
440: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.