|
|
1.1 root 1: /* Word-abbrev mode. Copyright (C) 1985 Richard M. Stallman.
2:
3: This file is part of GNU Emacs.
4:
5: GNU Emacs is distributed in the hope that it will be useful,
6: but WITHOUT ANY WARRANTY. No author or distributor
7: accepts responsibility to anyone for the consequences of using it
8: or for whether it serves any particular purpose or works at all,
9: unless he says so in writing. Refer to the GNU Emacs General Public
10: License for full details.
11:
12: Everyone is granted permission to copy, modify and redistribute
13: GNU Emacs, but only under the conditions described in the
14: GNU Emacs General Public License. A copy of this license is
15: supposed to have been given to you along with GNU Emacs so you
16: can know your rights and responsibilities. It should be in a
17: file named COPYING. Among other things, the copyright notice
18: and this notice must be preserved on all copies. */
19:
20:
21: #include "config.h"
22: #include <stdio.h>
23: #undef NULL
24: #include "lisp.h"
25: #include "commands.h"
26: #include "buffer.h"
27:
28: /* An abbrev table is an obarray.
29: Each defined abbrev is represented by a symbol in that obarray
30: whose print name is the abbreviation.
31: The symbol's value is a string which is the expansion.
32: If its function definition is non-nil, it is called
33: after the expansion is done.
34: The plist slot of the abbrev symbol is its usage count. */
35:
36: /* List of all abbrev-table name symbols:
37: symbols whose values are abbrev tables. */
38:
39: Lisp_Object Vabbrev_table_name_list;
40:
41: /* The table of global abbrevs. These are in effect
42: in any buffer in which abbrev mode is turned on. */
43:
44: Lisp_Object Vglobal_abbrev_table;
45:
46: /* The local abbrev table used by default (in Fundamental Mode buffers) */
47:
48: Lisp_Object Vfundamental_mode_abbrev_table;
49:
50: /* Set nonzero when an abbrev definition is changed */
51:
52: int abbrevs_changed;
53:
54: int abbrev_all_caps;
55:
56: /* Non-nil => use this location as the start of abbrev to expand
57: (rather than taking the word before point as the abbrev) */
58:
59: Lisp_Object Vabbrev_start_location;
60:
61: /* Buffer that Vabbrev_start_location applies to */
62: Lisp_Object Vabbrev_start_location_buffer;
63:
64: /* The symbol representing the abbrev most recently expanded */
65:
66: Lisp_Object Vlast_abbrev;
67:
68: /* Character address of start of last abbrev expanded */
69:
70: int last_abbrev_point;
71:
72: extern Lisp_Object oblookup ();
73:
74: DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
75: "Create a new, empty abbrev table object.")
76: ()
77: {
78: return Fmake_vector (make_number (59), make_number (0));
79: }
80:
81: DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
82: "Undefine all abbrevs in abbrev table TABLE, leaving it empty.")
83: (table)
84: Lisp_Object table;
85: {
86: int i, size;
87:
88: CHECK_VECTOR (table, 0);
89: size = XVECTOR (table)->size;
90: abbrevs_changed = 1;
91: for (i = 0; i < size; i++)
92: XVECTOR (table)->contents[i] = make_number (0);
93: return Qnil;
94: }
95:
96: DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 5, 0,
97: "Define an abbrev in TABLE named NAME, to expand to EXPANSION or call HOOK.\n\
98: NAME and EXPANSION are strings. HOOK is a function or nil.\n\
99: To undefine an abbrev, define it with EXPANSION = nil")
100: (table, name, expansion, hook, count)
101: Lisp_Object table, name, expansion, hook, count;
102: {
103: Lisp_Object sym, oexp, ohook, tem;
104: CHECK_VECTOR (table, 0);
105: CHECK_STRING (name, 1);
106: CHECK_STRING (expansion, 2);
107: if (NULL (count))
108: count = make_number (0);
109: else
110: CHECK_NUMBER (count, 0);
111:
112: sym = Fintern (name, table);
113:
114: oexp = XSYMBOL (sym)->value;
115: ohook = XSYMBOL (sym)->function;
116: if (!((EQ (oexp, expansion)
117: || (XTYPE (oexp) == Lisp_String
118: && (tem = Fstring_equal (oexp, expansion), !NULL (tem))))
119: &&
120: (EQ (ohook, hook)
121: || (tem = Fequal (ohook, hook), !NULL (tem)))))
122: abbrevs_changed = 1;
123:
124: Fset (sym, expansion);
125: Ffset (sym, hook);
126: Fsetplist (sym, count);
127:
128: return name;
129: }
130:
131: DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
132: "sDefine global abbrev: \nsExpansion for %s: ",
133: "Define ABBREV as a global abbreviation for EXPANSION.")
134: (name, expansion)
135: Lisp_Object name, expansion;
136: {
137: Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (name),
138: expansion, Qnil, make_number (0));
139: return name;
140: }
141:
142: DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
143: "sDefine mode abbrev: \nsExpansion for %s: ",
144: "Define ABBREV as a mode-specific abbreviation for EXPANSION.")
145: (name, expansion)
146: Lisp_Object name, expansion;
147: {
148: if (NULL (bf_cur->abbrev_table))
149: error ("No local abbrev table associated with this buffer");
150:
151: Fdefine_abbrev (bf_cur->abbrev_table, Fdowncase (name),
152: expansion, Qnil, make_number (0));
153: return name;
154: }
155:
156: DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
157: "Return the symbol representing abbrev named ABBREV.\n\
158: Value is nil if that abbrev is not defined.\n\
159: Optional second arg TABLE is abbrev table to look it up in.\n\
160: Default is try buffer's mode-specific abbrev table, then global table.")
161: (abbrev, table)
162: Lisp_Object abbrev, table;
163: {
164: Lisp_Object sym;
165: CHECK_STRING (abbrev, 0);
166: if (!NULL (table))
167: sym = Fintern_soft (abbrev, table);
168: else
169: {
170: sym = Qnil;
171: if (!NULL (bf_cur->abbrev_table))
172: sym = Fintern_soft (abbrev, bf_cur->abbrev_table);
173: if (NULL (XSYMBOL (sym)->value))
174: sym = Qnil;
175: if (NULL (sym))
176: sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
177: }
178: if (NULL (XSYMBOL (sym)->value)) return Qnil;
179: return sym;
180: }
181:
182: DEFUN ("abbrev-expansion", Fabbrev_expansion, Sabbrev_expansion, 1, 2, 0,
183: "Return the string that ABBREV expands into in the current buffer.\n\
184: Optionally specify an abbrev table; then ABBREV is looked up in that table only.")
185: (abbrev, table)
186: Lisp_Object abbrev, table;
187: {
188: Lisp_Object sym;
189: sym = Fabbrev_symbol (abbrev, table);
190: if (NULL (sym)) return sym;
191: return Fsymbol_value (sym);
192: }
193:
194: /* Expand the word before point, if it is an abbrev.
195: Returns 1 if an expansion is done. */
196:
197: DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
198: "Expand the abbrev before point, if it is an abbrev.\n\
199: Returns t if expansion took place.")
200: ()
201: {
202: char buffer[200];
203: char *p = buffer;
204: int wordstart, idx;
205: int uccount = 0, lccount = 0;
206: Lisp_Object sym, expansion, hook, tem;
207:
208: if (XBUFFER (Vabbrev_start_location_buffer) != bf_cur)
209: Vabbrev_start_location = Qnil;
210: if (!NULL (Vabbrev_start_location))
211: {
212: tem = Vabbrev_start_location;
213: CHECK_NUMBER_COERCE_MARKER (tem, 0);
214: wordstart = XINT (tem);
215: Vabbrev_start_location = Qnil;
216: }
217: else
218: wordstart = scan_words (point, -1);
219:
220: if (!wordstart || point - wordstart >= sizeof buffer || point <= wordstart)
221: return Qnil;
222:
223: for (idx = wordstart; idx < point; idx++)
224: {
225: *p = CharAt (idx);
226: if (*p >= 'A' && *p <= 'Z')
227: *p += 040, uccount++;
228: else if (*p >= 'a' && *p <= 'z')
229: lccount++;
230: p++;
231: }
232:
233: if (XTYPE (bf_cur->abbrev_table) == Lisp_Vector)
234: sym = oblookup (bf_cur->abbrev_table, buffer, p - buffer);
235: else
236: XFASTINT (sym) = 0;
237: if (XTYPE (sym) == Lisp_Int ||
238: NULL (XSYMBOL (sym)->value))
239: sym = oblookup (Vglobal_abbrev_table, buffer, p - buffer);
240: if (XTYPE (sym) == Lisp_Int ||
241: NULL (XSYMBOL (sym)->value))
242: return Qnil;
243:
244: SetPoint (wordstart);
245: del_range (point, point + (p - buffer));
246:
247: /* Now sym is the abbrev symbol. */
248: Vlast_abbrev = sym;
249: last_abbrev_point = point;
250:
251: if (XTYPE (XSYMBOL (sym)->plist) == Lisp_Int)
252: XSETINT (XSYMBOL (sym)->plist,
253: XINT (XSYMBOL (sym)->plist) + 1); /* Increment use count */
254:
255: hook = XSYMBOL (sym)->function;
256: if (!NULL (hook))
257: Fapply (hook, Qnil);
258: else
259: {
260: expansion = XSYMBOL (sym)->value;
261: InsCStr (XSTRING (expansion)->data, XSTRING (expansion)->size);
262:
263: if (uccount && !lccount)
264: {
265: /* Abbrev was all caps */
266: /* If expansion is multiple words, normally capitalize each word */
267: /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
268: but Megatest 68000 compiler can't handle that */
269: if (!abbrev_all_caps)
270: if (scan_words (point, -1) > scan_words (wordstart, 1))
271: {
272: upcase_initials_region (make_number (wordstart),
273: make_number (point));
274: goto caped;
275: }
276: /* If expansion is one word, or if user says so, upcase it all. */
277: Fupcase_region (make_number (wordstart), make_number (point));
278: caped: ;
279: }
280: else if (uccount)
281: {
282: /* Abbrev included some caps. Cap first initial of expansion */
283: idx = point;
284: SetPoint (wordstart);
285: Fcapitalize_word (make_number (1));
286: SetPoint (idx);
287: }
288: }
289:
290: return Qt;
291: }
292:
293: DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
294: "Undo the expansion of the last abbrev that expanded.")
295: ()
296: {
297: SetPoint (last_abbrev_point);
298: if (NULL (Vlast_abbrev))
299: {
300: Fforward_word (make_number (1));
301: Fexpand_abbrev ();
302: }
303: else if (XTYPE (Vlast_abbrev) == Lisp_Symbol)
304: {
305: del_range (point, point + XSTRING (XSYMBOL (Vlast_abbrev)->value)->size);
306: InsCStr (XSYMBOL (Vlast_abbrev)->name->data, XSYMBOL (Vlast_abbrev)->name->size);
307: Vlast_abbrev = Qnil;
308: }
309: return Qnil;
310: }
311:
312: DEFUN ("last-abbrev-expansion", Flast_abbrev_expansion, Slast_abbrev_expansion, 0, 0, 0,
313: "Return expansion of last abbrev expanded, or nil.")
314: ()
315: {
316: return Fsymbol_value (Vlast_abbrev);
317: }
318:
319: static
320: write_abbrev (sym, stream)
321: Lisp_Object sym, stream;
322: {
323: Lisp_Object name;
324: if (NULL (XSYMBOL (sym)->value))
325: return;
326: InsCStr (" (", 5);
327: XSET (name, Lisp_String, XSYMBOL (sym)->name);
328: Fprin1 (name, stream);
329: InsCStr (" ", 1);
330: Fprin1 (XSYMBOL (sym)->value, stream);
331: InsCStr (" ", 1);
332: Fprin1 (XSYMBOL (sym)->function, stream);
333: InsCStr (" ", 1);
334: Fprin1 (XSYMBOL (sym)->plist, stream);
335: InsCStr (")\n", 2);
336: }
337:
338: static
339: describe_abbrev (sym, stream)
340: Lisp_Object sym, stream;
341: {
342: Lisp_Object one;
343:
344: if (NULL (XSYMBOL (sym)->value))
345: return;
346: one = make_number (1);
347: Fprin1 (Fsymbol_name (sym), stream);
348: Findent_to (make_number (15), one);
349: Fprin1 (XSYMBOL (sym)->plist, stream);
350: Findent_to (make_number (20), one);
351: Fprin1 (XSYMBOL (sym)->value, stream);
352: if (!NULL (XSYMBOL (sym)->function))
353: {
354: Findent_to (make_number (45), one);
355: Fprin1 (XSYMBOL (sym)->function, stream);
356: }
357: Fterpri (stream);
358: }
359:
360: DEFUN ("insert-abbrev-table-description",
361: Finsert_abbrev_table_description, Sinsert_abbrev_table_description,
362: 2, 2, 0,
363: "Insert before point a description of abbrev table named NAME.\n\
364: NAME is a symbol whose value is an abbrev table.\n\
365: If 2nd arg READABLE is non-nil, a readable description is inserted.\n\
366: Otherwise description is an expression,\n\
367: a call to define-abbrev-table which would\n\
368: define NAME exactly as it is currently defined.")
369: (name, readable)
370: Lisp_Object name, readable;
371: {
372: Lisp_Object table;
373: Lisp_Object stream;
374:
375: CHECK_SYMBOL (name, 0);
376: table = Fsymbol_value (name);
377: CHECK_VECTOR (table, 0);
378:
379: XSET (stream, Lisp_Buffer, bf_cur);
380:
381: if (!NULL (readable))
382: {
383: InsStr ("(");
384: Fprin1 (name, stream);
385: InsStr (")\n\n");
386: map_obarray (table, describe_abbrev, stream);
387: InsStr ("\n\n");
388: }
389: else
390: {
391: InsStr ("(define-abbrev-table '");
392: Fprin1 (name, stream);
393: InsStr (" '(\n");
394: map_obarray (table, write_abbrev, stream);
395: InsStr (" ))\n\n");
396: }
397:
398: return Qnil;
399: }
400:
401: DEFUN ("define-abbrev-table",
402: Fdefine_abbrev_table, Sdefine_abbrev_table, 2, 2, 0,
403: "Define TABNAME (a symbol) as an abbrev table name.\n\
404: Define abbrevs in it according to DEFINITIONS, a list of elements\n\
405: of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
406: (tabname, defns)
407: Lisp_Object tabname, defns;
408: {
409: Lisp_Object name, exp, hook, count;
410: Lisp_Object table, elt;
411:
412: CHECK_SYMBOL (tabname, 0);
413: table = Fboundp (tabname);
414: if (NULL (table) || (table = Fsymbol_value (tabname), NULL (table)))
415: {
416: table = Fmake_abbrev_table ();
417: Fset (tabname, table);
418: Vabbrev_table_name_list =
419: Fcons (tabname, Vabbrev_table_name_list);
420: }
421: CHECK_VECTOR (table, 0);
422:
423: for (;!NULL (defns); defns = Fcdr (defns))
424: {
425: elt = Fcar (defns);
426: name = Fcar (elt);
427: elt = Fcdr (elt);
428: exp = Fcar (elt);
429: elt = Fcdr (elt);
430: hook = Fcar (elt);
431: elt = Fcdr (elt);
432: count = Fcar (elt);
433: Fdefine_abbrev (table, name, exp, hook, count);
434: }
435: return Qnil;
436: }
437:
438: syms_of_abbrev ()
439: {
440: DefLispVar ("abbrev-table-name-list", &Vabbrev_table_name_list,
441: "List of symbols whose values are abbrev tables.");
442: Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
443: Fcons (intern ("global-abbrev-table"),
444: Qnil));
445:
446: DefLispVar ("global-abbrev-table", &Vglobal_abbrev_table,
447: "The abbrev table whose abbrevs affect all buffers.\n\
448: Each buffer may also have a local abbrev table.\n\
449: If it does, the local table overrides the global one\n\
450: for any particular abbrev defined in both.");
451: Vglobal_abbrev_table = Fmake_abbrev_table ();
452:
453: DefLispVar ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
454: "The abbrev table of mode-specific abbrevs for Fundamental Mode.");
455: Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
456: bf_cur->abbrev_table = Vfundamental_mode_abbrev_table;
457:
458: /* Avoid need for some error checking this way
459: DefLispVar ("last-abbrev", &Vlast_abbrev,
460: "The abbrev-symbol of the last abbrev expanded.");
461:
462: DefIntVar ("last-abbrev-location", &last_abbrev_point,
463: "The location of the last abbrev expanded.");
464: */
465: staticpro (&Vlast_abbrev);
466: Vlast_abbrev = Qnil;
467: last_abbrev_point = 0;
468:
469: DefLispVar ("abbrev-start-location", &Vabbrev_start_location,
470: "Buffer position for expand-abbrev to use as the start of the abbrev.\n\
471: nil means use the word before point as the abbrev.\n\
472: Set to nil each time expand-abbrev is called.");
473: Vabbrev_start_location = Qnil;
474:
475: DefLispVar ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
476: "Buffer that abbrev-start-location has been set for.\n\
477: Trying to expand an abbrev in any other buffer clears abbrev-start-location.");
478: Vabbrev_start_location_buffer = Qnil;
479:
480: DefBufferLispVar ("local-abbrev-table", &bf_cur->abbrev_table,
481: "Local (mode-specific) abbrev table of current buffer.");
482:
483: DefBoolVar ("abbrevs-changed", &abbrevs_changed,
484: "Set non-nil by defining or altering any word abbrevs.");
485: abbrevs_changed = 0;
486:
487: DefBoolVar ("abbrev-all-caps", &abbrev_all_caps,
488: "*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
489: abbrev_all_caps = 0;
490:
491: defsubr (&Smake_abbrev_table);
492: defsubr (&Sclear_abbrev_table);
493: defsubr (&Sdefine_abbrev);
494: defsubr (&Sdefine_global_abbrev);
495: defsubr (&Sdefine_mode_abbrev);
496: defsubr (&Sabbrev_expansion);
497: defsubr (&Sabbrev_symbol);
498: defsubr (&Sexpand_abbrev);
499: defsubr (&Sunexpand_abbrev);
500: defsubr (&Slast_abbrev_expansion);
501: defsubr (&Sinsert_abbrev_table_description);
502: defsubr (&Sdefine_abbrev_table);
503: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.