]> code.delx.au - gnu-emacs/blob - src/abbrev.c
Merge from emacs--devo--0
[gnu-emacs] / src / abbrev.c
1 /* Primitives for word-abbrev mode.
2 Copyright (C) 1985, 1986, 1993, 1996, 1998, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22
23 #include <config.h>
24 #include <stdio.h>
25
26 #include "lisp.h"
27 #include "commands.h"
28 #include "buffer.h"
29 #include "window.h"
30 #include "character.h"
31 #include "syntax.h"
32
33 /* An abbrev table is an obarray.
34 Each defined abbrev is represented by a symbol in that obarray
35 whose print name is the abbreviation.
36 The symbol's value is a string which is the expansion.
37 If its function definition is non-nil, it is called
38 after the expansion is done.
39 The plist slot of the abbrev symbol is its usage count. */
40
41 /* List of all abbrev-table name symbols:
42 symbols whose values are abbrev tables. */
43
44 Lisp_Object Vabbrev_table_name_list;
45
46 /* The table of global abbrevs. These are in effect
47 in any buffer in which abbrev mode is turned on. */
48
49 Lisp_Object Vglobal_abbrev_table;
50
51 /* The local abbrev table used by default (in Fundamental Mode buffers) */
52
53 Lisp_Object Vfundamental_mode_abbrev_table;
54
55 /* Set nonzero when an abbrev definition is changed */
56
57 int abbrevs_changed;
58
59 int abbrev_all_caps;
60
61 /* Non-nil => use this location as the start of abbrev to expand
62 (rather than taking the word before point as the abbrev) */
63
64 Lisp_Object Vabbrev_start_location;
65
66 /* Buffer that Vabbrev_start_location applies to */
67 Lisp_Object Vabbrev_start_location_buffer;
68
69 /* The symbol representing the abbrev most recently expanded */
70
71 Lisp_Object Vlast_abbrev;
72
73 /* A string for the actual text of the abbrev most recently expanded.
74 This has more info than Vlast_abbrev since case is significant. */
75
76 Lisp_Object Vlast_abbrev_text;
77
78 /* Character address of start of last abbrev expanded */
79
80 EMACS_INT last_abbrev_point;
81
82 /* Hook to run before expanding any abbrev. */
83
84 Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
85
86 Lisp_Object Qsystem_type, Qcount, Qforce;
87 \f
88 DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
89 doc: /* Create a new, empty abbrev table object. */)
90 ()
91 {
92 /* The value 59 is arbitrary chosen prime number. */
93 return Fmake_vector (make_number (59), make_number (0));
94 }
95
96 DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
97 doc: /* Undefine all abbrevs in abbrev table TABLE, leaving it empty. */)
98 (table)
99 Lisp_Object table;
100 {
101 int i, size;
102
103 CHECK_VECTOR (table);
104 size = XVECTOR (table)->size;
105 abbrevs_changed = 1;
106 for (i = 0; i < size; i++)
107 XVECTOR (table)->contents[i] = make_number (0);
108 return Qnil;
109 }
110
111 DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 6, 0,
112 doc: /* Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.
113 NAME must be a string, and should be lower-case.
114 EXPANSION should usually be a string.
115 To undefine an abbrev, define it with EXPANSION = nil.
116 If HOOK is non-nil, it should be a function of no arguments;
117 it is called after EXPANSION is inserted.
118 If EXPANSION is not a string, the abbrev is a special one,
119 which does not expand in the usual way but only runs HOOK.
120
121 COUNT, if specified, gives the initial value for the abbrev's
122 usage-count, which is incremented each time the abbrev is used.
123 \(The default is zero.)
124
125 SYSTEM-FLAG, if non-nil, says that this is a "system" abbreviation
126 which should not be saved in the user's abbreviation file.
127 Unless SYSTEM-FLAG is `force', a system abbreviation will not
128 overwrite a non-system abbreviation of the same name. */)
129 (table, name, expansion, hook, count, system_flag)
130 Lisp_Object table, name, expansion, hook, count, system_flag;
131 {
132 Lisp_Object sym, oexp, ohook, tem;
133 CHECK_VECTOR (table);
134 CHECK_STRING (name);
135
136 /* If defining a system abbrev, do not overwrite a non-system abbrev
137 of the same name, unless 'force is used. */
138 if (!NILP (system_flag) && !EQ (system_flag, Qforce))
139 {
140 sym = Fintern_soft (name, table);
141
142 if (!NILP (SYMBOL_VALUE (sym)) &&
143 NILP (Fplist_get (XSYMBOL (sym)->plist, Qsystem_type))) return Qnil;
144 }
145
146 if (NILP (count))
147 count = make_number (0);
148 else
149 CHECK_NUMBER (count);
150
151 sym = Fintern (name, table);
152
153 oexp = SYMBOL_VALUE (sym);
154 ohook = XSYMBOL (sym)->function;
155 if (!((EQ (oexp, expansion)
156 || (STRINGP (oexp) && STRINGP (expansion)
157 && (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
158 &&
159 (EQ (ohook, hook)
160 || (tem = Fequal (ohook, hook), !NILP (tem))))
161 && NILP (system_flag))
162 abbrevs_changed = 1;
163
164 Fset (sym, expansion);
165 Ffset (sym, hook);
166
167 if (! NILP (system_flag))
168 Fsetplist (sym, list4 (Qcount, count, Qsystem_type, system_flag));
169 else
170 Fsetplist (sym, count);
171
172 return name;
173 }
174
175 /* Check if the characters in ABBREV have word syntax in either the
176 * current (if global == 0) or standard syntax table. */
177 static void
178 abbrev_check_chars (abbrev, global)
179 Lisp_Object abbrev;
180 int global;
181 {
182 int i, i_byte, len, nbad = 0;
183 int j, found, nuniq = 0;
184 char *badchars, *baduniq;
185
186 CHECK_STRING (abbrev);
187 len = SCHARS (abbrev);
188
189 badchars = (char *) alloca (len + 1);
190
191 for (i = 0, i_byte = 0; i < len; )
192 {
193 int c;
194
195 FETCH_STRING_CHAR_ADVANCE (c, abbrev, i, i_byte);
196
197 if (global)
198 {
199 /* Copied from SYNTAX in syntax.h, except using FOLLOW_PARENT. */
200 Lisp_Object syntax_temp
201 = SYNTAX_ENTRY_FOLLOW_PARENT (Vstandard_syntax_table, c);
202 if ( (CONSP (syntax_temp)
203 ? (enum syntaxcode) (XINT (XCAR (syntax_temp)) & 0xff)
204 : Swhitespace) != Sword ) badchars[nbad++] = c;
205 }
206 else if (SYNTAX (c) != Sword)
207 badchars[nbad++] = c;
208 }
209
210 if (nbad == 0) return;
211
212 baduniq = (char *) alloca (nbad + 1);
213
214 for (i = 0; i < nbad; i++)
215 {
216 found = 0;
217
218 for (j = 0; j < nuniq; j++)
219 {
220 if (badchars[i] == baduniq[j])
221 {
222 found = 1;
223 break;
224 }
225 }
226
227 if (found) continue ;
228
229 baduniq[nuniq++] = badchars[i];
230 }
231
232 baduniq[nuniq] = '\0';
233
234 error ("Some abbrev characters (%s) are not word constituents %s",
235 baduniq, global ? "in the standard syntax" : "in this mode" );
236 }
237
238 DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
239 "sDefine global abbrev: \nsExpansion for %s: ",
240 doc: /* Define ABBREV as a global abbreviation for EXPANSION.
241 The characters in ABBREV must all be word constituents in the standard
242 syntax table. */)
243 (abbrev, expansion)
244 Lisp_Object abbrev, expansion;
245 {
246 abbrev_check_chars (abbrev, 1);
247
248 Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (abbrev),
249 expansion, Qnil, make_number (0), Qnil);
250 return abbrev;
251 }
252
253 DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
254 "sDefine mode abbrev: \nsExpansion for %s: ",
255 doc: /* Define ABBREV as a mode-specific abbreviation for EXPANSION.
256 The characters in ABBREV must all be word-constituents in the current mode. */)
257 (abbrev, expansion)
258 Lisp_Object abbrev, expansion;
259 {
260 if (NILP (current_buffer->abbrev_table))
261 error ("Major mode has no abbrev table");
262
263 abbrev_check_chars (abbrev, 0);
264
265 Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (abbrev),
266 expansion, Qnil, make_number (0), Qnil);
267 return abbrev;
268 }
269
270 DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
271 doc: /* Return the symbol representing abbrev named ABBREV.
272 This symbol's name is ABBREV, but it is not the canonical symbol of that name;
273 it is interned in an abbrev-table rather than the normal obarray.
274 The value is nil if that abbrev is not defined.
275 Optional second arg TABLE is abbrev table to look it up in.
276 The default is to try buffer's mode-specific abbrev table, then global table. */)
277 (abbrev, table)
278 Lisp_Object abbrev, table;
279 {
280 Lisp_Object sym;
281 CHECK_STRING (abbrev);
282 if (!NILP (table))
283 sym = Fintern_soft (abbrev, table);
284 else
285 {
286 sym = Qnil;
287 if (!NILP (current_buffer->abbrev_table))
288 sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
289 if (NILP (SYMBOL_VALUE (sym)))
290 sym = Qnil;
291 if (NILP (sym))
292 sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
293 }
294 if (NILP (SYMBOL_VALUE (sym)))
295 return Qnil;
296 return sym;
297 }
298
299 DEFUN ("abbrev-expansion", Fabbrev_expansion, Sabbrev_expansion, 1, 2, 0,
300 doc: /* Return the string that ABBREV expands into in the current buffer.
301 Optionally specify an abbrev table as second arg;
302 then ABBREV is looked up in that table only. */)
303 (abbrev, table)
304 Lisp_Object abbrev, table;
305 {
306 Lisp_Object sym;
307 sym = Fabbrev_symbol (abbrev, table);
308 if (NILP (sym)) return sym;
309 return Fsymbol_value (sym);
310 }
311 \f
312 /* Expand the word before point, if it is an abbrev.
313 Returns 1 if an expansion is done. */
314
315 DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
316 doc: /* Expand the abbrev before point, if there is an abbrev there.
317 Effective when explicitly called even when `abbrev-mode' is nil.
318 Returns the abbrev symbol, if expansion took place. */)
319 ()
320 {
321 register char *buffer, *p;
322 int wordstart, wordend;
323 register int wordstart_byte, wordend_byte, idx, idx_byte;
324 int whitecnt;
325 int uccount = 0, lccount = 0;
326 register Lisp_Object sym;
327 Lisp_Object expansion, hook, tem;
328 Lisp_Object value;
329 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
330
331 value = Qnil;
332
333 Frun_hooks (1, &Qpre_abbrev_expand_hook);
334
335 wordstart = 0;
336 if (!(BUFFERP (Vabbrev_start_location_buffer)
337 && XBUFFER (Vabbrev_start_location_buffer) == current_buffer))
338 Vabbrev_start_location = Qnil;
339 if (!NILP (Vabbrev_start_location))
340 {
341 tem = Vabbrev_start_location;
342 CHECK_NUMBER_COERCE_MARKER (tem);
343 wordstart = XINT (tem);
344 Vabbrev_start_location = Qnil;
345 if (wordstart < BEGV || wordstart > ZV)
346 wordstart = 0;
347 if (wordstart && wordstart != ZV)
348 {
349 wordstart_byte = CHAR_TO_BYTE (wordstart);
350 if (FETCH_BYTE (wordstart_byte) == '-')
351 del_range (wordstart, wordstart + 1);
352 }
353 }
354 if (!wordstart)
355 wordstart = scan_words (PT, -1);
356
357 if (!wordstart)
358 return value;
359
360 wordstart_byte = CHAR_TO_BYTE (wordstart);
361 wordend = scan_words (wordstart, 1);
362 if (!wordend)
363 return value;
364
365 if (wordend > PT)
366 wordend = PT;
367
368 wordend_byte = CHAR_TO_BYTE (wordend);
369 whitecnt = PT - wordend;
370 if (wordend <= wordstart)
371 return value;
372
373 p = buffer = (char *) alloca (wordend_byte - wordstart_byte);
374
375 for (idx = wordstart, idx_byte = wordstart_byte; idx < wordend; )
376 {
377 register int c;
378
379 if (multibyte)
380 {
381 FETCH_CHAR_ADVANCE (c, idx, idx_byte);
382 }
383 else
384 {
385 c = FETCH_BYTE (idx_byte);
386 idx++, idx_byte++;
387 }
388
389 if (UPPERCASEP (c))
390 c = DOWNCASE (c), uccount++;
391 else if (! NOCASEP (c))
392 lccount++;
393 if (multibyte)
394 p += CHAR_STRING (c, p);
395 else
396 *p++ = c;
397 }
398
399 if (VECTORP (current_buffer->abbrev_table))
400 sym = oblookup (current_buffer->abbrev_table, buffer,
401 wordend - wordstart, p - buffer);
402 else
403 XSETFASTINT (sym, 0);
404
405 if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym)))
406 sym = oblookup (Vglobal_abbrev_table, buffer,
407 wordend - wordstart, p - buffer);
408 if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym)))
409 return value;
410
411 if (INTERACTIVE && !EQ (minibuf_window, selected_window))
412 {
413 /* Add an undo boundary, in case we are doing this for
414 a self-inserting command which has avoided making one so far. */
415 SET_PT (wordend);
416 Fundo_boundary ();
417 }
418
419 Vlast_abbrev_text
420 = Fbuffer_substring (make_number (wordstart), make_number (wordend));
421
422 /* Now sym is the abbrev symbol. */
423 Vlast_abbrev = sym;
424 value = sym;
425 last_abbrev_point = wordstart;
426
427 /* Increment use count. */
428 if (INTEGERP (XSYMBOL (sym)->plist))
429 XSETINT (XSYMBOL (sym)->plist,
430 XINT (XSYMBOL (sym)->plist) + 1);
431 else if (INTEGERP (tem = Fget (sym, Qcount)))
432 Fput (sym, Qcount, make_number (XINT (tem) + 1));
433
434 /* If this abbrev has an expansion, delete the abbrev
435 and insert the expansion. */
436 expansion = SYMBOL_VALUE (sym);
437 if (STRINGP (expansion))
438 {
439 SET_PT (wordstart);
440
441 insert_from_string (expansion, 0, 0, SCHARS (expansion),
442 SBYTES (expansion), 1);
443 del_range_both (PT, PT_BYTE,
444 wordend + (PT - wordstart),
445 wordend_byte + (PT_BYTE - wordstart_byte),
446 1);
447
448 SET_PT (PT + whitecnt);
449
450 if (uccount && !lccount)
451 {
452 /* Abbrev was all caps */
453 /* If expansion is multiple words, normally capitalize each word */
454 /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
455 but Megatest 68000 compiler can't handle that */
456 if (!abbrev_all_caps)
457 if (scan_words (PT, -1) > scan_words (wordstart, 1))
458 {
459 Fupcase_initials_region (make_number (wordstart),
460 make_number (PT));
461 goto caped;
462 }
463 /* If expansion is one word, or if user says so, upcase it all. */
464 Fupcase_region (make_number (wordstart), make_number (PT));
465 caped: ;
466 }
467 else if (uccount)
468 {
469 /* Abbrev included some caps. Cap first initial of expansion */
470 int pos = wordstart_byte;
471
472 /* Find the initial. */
473 if (multibyte)
474 while (pos < PT_BYTE
475 && SYNTAX (FETCH_MULTIBYTE_CHAR (pos)) != Sword)
476 INC_POS (pos);
477 else
478 while (pos < PT_BYTE
479 && (SYNTAX (*BUF_BYTE_ADDRESS (current_buffer, pos))
480 != Sword))
481 pos++;
482
483 /* Change just that. */
484 pos = BYTE_TO_CHAR (pos);
485 Fupcase_initials_region (make_number (pos), make_number (pos + 1));
486 }
487 }
488
489 hook = XSYMBOL (sym)->function;
490 if (!NILP (hook))
491 {
492 Lisp_Object expanded, prop;
493
494 /* If the abbrev has a hook function, run it. */
495 expanded = call0 (hook);
496
497 /* In addition, if the hook function is a symbol with
498 a non-nil `no-self-insert' property, let the value it returned
499 specify whether we consider that an expansion took place. If
500 it returns nil, no expansion has been done. */
501
502 if (SYMBOLP (hook)
503 && NILP (expanded)
504 && (prop = Fget (hook, intern ("no-self-insert")),
505 !NILP (prop)))
506 value = Qnil;
507 }
508
509 return value;
510 }
511
512 DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
513 doc: /* Undo the expansion of the last abbrev that expanded.
514 This differs from ordinary undo in that other editing done since then
515 is not undone. */)
516 ()
517 {
518 int opoint = PT;
519 int adjust = 0;
520 if (last_abbrev_point < BEGV
521 || last_abbrev_point > ZV)
522 return Qnil;
523 SET_PT (last_abbrev_point);
524 if (STRINGP (Vlast_abbrev_text))
525 {
526 /* This isn't correct if Vlast_abbrev->function was used
527 to do the expansion */
528 Lisp_Object val;
529 int zv_before;
530
531 val = SYMBOL_VALUE (Vlast_abbrev);
532 if (!STRINGP (val))
533 error ("Value of `abbrev-symbol' must be a string");
534 zv_before = ZV;
535 del_range_byte (PT_BYTE, PT_BYTE + SBYTES (val), 1);
536 /* Don't inherit properties here; just copy from old contents. */
537 insert_from_string (Vlast_abbrev_text, 0, 0,
538 SCHARS (Vlast_abbrev_text),
539 SBYTES (Vlast_abbrev_text), 0);
540 Vlast_abbrev_text = Qnil;
541 /* Total number of characters deleted. */
542 adjust = ZV - zv_before;
543 }
544 SET_PT (last_abbrev_point < opoint ? opoint + adjust : opoint);
545 return Qnil;
546 }
547 \f
548 static void
549 write_abbrev (sym, stream)
550 Lisp_Object sym, stream;
551 {
552 Lisp_Object name, count, system_flag;
553
554 if (INTEGERP (XSYMBOL (sym)->plist))
555 {
556 count = XSYMBOL (sym)->plist;
557 system_flag = Qnil;
558 }
559 else
560 {
561 count = Fget (sym, Qcount);
562 system_flag = Fget (sym, Qsystem_type);
563 }
564
565 if (NILP (SYMBOL_VALUE (sym)) || ! NILP (system_flag))
566 return;
567
568 insert (" (", 5);
569 name = SYMBOL_NAME (sym);
570 Fprin1 (name, stream);
571 insert (" ", 1);
572 Fprin1 (SYMBOL_VALUE (sym), stream);
573 insert (" ", 1);
574 Fprin1 (XSYMBOL (sym)->function, stream);
575 insert (" ", 1);
576 Fprin1 (count, stream);
577 insert (")\n", 2);
578 }
579
580 static void
581 describe_abbrev (sym, stream)
582 Lisp_Object sym, stream;
583 {
584 Lisp_Object one, count, system_flag;
585
586 if (INTEGERP (XSYMBOL (sym)->plist))
587 {
588 count = XSYMBOL (sym)->plist;
589 system_flag = Qnil;
590 }
591 else
592 {
593 count = Fget (sym, Qcount);
594 system_flag = Fget (sym, Qsystem_type);
595 }
596
597 if (NILP (SYMBOL_VALUE (sym)))
598 return;
599
600 one = make_number (1);
601 Fprin1 (Fsymbol_name (sym), stream);
602
603 if (!NILP (system_flag))
604 {
605 insert_string (" (sys)");
606 Findent_to (make_number (20), one);
607 }
608 else
609 Findent_to (make_number (15), one);
610
611 Fprin1 (count, stream);
612 Findent_to (make_number (20), one);
613 Fprin1 (SYMBOL_VALUE (sym), stream);
614 if (!NILP (XSYMBOL (sym)->function))
615 {
616 Findent_to (make_number (45), one);
617 Fprin1 (XSYMBOL (sym)->function, stream);
618 }
619 Fterpri (stream);
620 }
621
622 static void
623 record_symbol (sym, list)
624 Lisp_Object sym, list;
625 {
626 XSETCDR (list, Fcons (sym, XCDR (list)));
627 }
628
629 DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,
630 Sinsert_abbrev_table_description, 1, 2, 0,
631 doc: /* Insert before point a full description of abbrev table named NAME.
632 NAME is a symbol whose value is an abbrev table.
633 If optional 2nd arg READABLE is non-nil, a human-readable description
634 is inserted. Otherwise the description is an expression,
635 a call to `define-abbrev-table', which would
636 define the abbrev table NAME exactly as it is currently defined.
637
638 Abbrevs marked as "system abbrevs" are normally omitted. However, if
639 READABLE is non-nil, they are listed. */)
640 (name, readable)
641 Lisp_Object name, readable;
642 {
643 Lisp_Object table;
644 Lisp_Object symbols;
645 Lisp_Object stream;
646
647 CHECK_SYMBOL (name);
648 table = Fsymbol_value (name);
649 CHECK_VECTOR (table);
650
651 XSETBUFFER (stream, current_buffer);
652
653 symbols = Fcons (Qnil, Qnil);
654 map_obarray (table, record_symbol, symbols);
655 symbols = XCDR (symbols);
656 symbols = Fsort (symbols, Qstring_lessp);
657
658 if (!NILP (readable))
659 {
660 insert_string ("(");
661 Fprin1 (name, stream);
662 insert_string (")\n\n");
663 while (! NILP (symbols))
664 {
665 describe_abbrev (XCAR (symbols), stream);
666 symbols = XCDR (symbols);
667 }
668
669 insert_string ("\n\n");
670 }
671 else
672 {
673 insert_string ("(define-abbrev-table '");
674 Fprin1 (name, stream);
675 insert_string (" '(\n");
676 while (! NILP (symbols))
677 {
678 write_abbrev (XCAR (symbols), stream);
679 symbols = XCDR (symbols);
680 }
681 insert_string (" ))\n\n");
682 }
683
684 return Qnil;
685 }
686 \f
687 DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
688 2, 2, 0,
689 doc: /* Define TABLENAME (a symbol) as an abbrev table name.
690 Define abbrevs in it according to DEFINITIONS, which is a list of elements
691 of the form (ABBREVNAME EXPANSION HOOK USECOUNT SYSTEMFLAG).
692 \(If the list is shorter than that, omitted elements default to nil). */)
693 (tablename, definitions)
694 Lisp_Object tablename, definitions;
695 {
696 Lisp_Object name, exp, hook, count;
697 Lisp_Object table, elt, sys;
698
699 CHECK_SYMBOL (tablename);
700 table = Fboundp (tablename);
701 if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
702 {
703 table = Fmake_abbrev_table ();
704 Fset (tablename, table);
705 Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
706 }
707 CHECK_VECTOR (table);
708
709 for (; CONSP (definitions); definitions = XCDR (definitions))
710 {
711 elt = XCAR (definitions);
712 name = Fcar (elt); elt = Fcdr (elt);
713 exp = Fcar (elt); elt = Fcdr (elt);
714 hook = Fcar (elt); elt = Fcdr (elt);
715 count = Fcar (elt); elt = Fcdr (elt);
716 sys = Fcar (elt);
717 Fdefine_abbrev (table, name, exp, hook, count, sys);
718 }
719 return Qnil;
720 }
721 \f
722 void
723 syms_of_abbrev ()
724 {
725 Qsystem_type = intern ("system-type");
726 staticpro (&Qsystem_type);
727
728 Qcount = intern ("count");
729 staticpro (&Qcount);
730
731 Qforce = intern ("force");
732 staticpro (&Qforce);
733
734 DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
735 doc: /* List of symbols whose values are abbrev tables. */);
736 Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
737 Fcons (intern ("global-abbrev-table"),
738 Qnil));
739
740 DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
741 doc: /* The abbrev table whose abbrevs affect all buffers.
742 Each buffer may also have a local abbrev table.
743 If it does, the local table overrides the global one
744 for any particular abbrev defined in both. */);
745 Vglobal_abbrev_table = Fmake_abbrev_table ();
746
747 DEFVAR_LISP ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
748 doc: /* The abbrev table of mode-specific abbrevs for Fundamental Mode. */);
749 Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
750 current_buffer->abbrev_table = Vfundamental_mode_abbrev_table;
751 buffer_defaults.abbrev_table = Vfundamental_mode_abbrev_table;
752
753 DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
754 doc: /* The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'. */);
755
756 DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
757 doc: /* The exact text of the last abbrev expanded.
758 A value of nil means the abbrev has already been unexpanded. */);
759
760 DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
761 doc: /* The location of the start of the last abbrev expanded. */);
762
763 Vlast_abbrev = Qnil;
764 Vlast_abbrev_text = Qnil;
765 last_abbrev_point = 0;
766
767 DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
768 doc: /* Buffer position for `expand-abbrev' to use as the start of the abbrev.
769 When nil, use the word before point as the abbrev.
770 Calling `expand-abbrev' sets this to nil. */);
771 Vabbrev_start_location = Qnil;
772
773 DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
774 doc: /* Buffer that `abbrev-start-location' has been set for.
775 Trying to expand an abbrev in any other buffer clears `abbrev-start-location'. */);
776 Vabbrev_start_location_buffer = Qnil;
777
778 DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
779 doc: /* Local (mode-specific) abbrev table of current buffer. */);
780
781 DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
782 doc: /* Set non-nil by defining or altering any word abbrevs.
783 This causes `save-some-buffers' to offer to save the abbrevs. */);
784 abbrevs_changed = 0;
785
786 DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
787 doc: /* *Set non-nil means expand multi-word abbrevs all caps if abbrev was so. */);
788 abbrev_all_caps = 0;
789
790 DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
791 doc: /* Function or functions to be called before abbrev expansion is done.
792 This is the first thing that `expand-abbrev' does, and so this may change
793 the current abbrev table before abbrev lookup happens. */);
794 Vpre_abbrev_expand_hook = Qnil;
795 Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
796 staticpro (&Qpre_abbrev_expand_hook);
797
798 defsubr (&Smake_abbrev_table);
799 defsubr (&Sclear_abbrev_table);
800 defsubr (&Sdefine_abbrev);
801 defsubr (&Sdefine_global_abbrev);
802 defsubr (&Sdefine_mode_abbrev);
803 defsubr (&Sabbrev_expansion);
804 defsubr (&Sabbrev_symbol);
805 defsubr (&Sexpand_abbrev);
806 defsubr (&Sunexpand_abbrev);
807 defsubr (&Sinsert_abbrev_table_description);
808 defsubr (&Sdefine_abbrev_table);
809 }
810
811 /* arch-tag: b721db69-f633-44a8-a361-c275acbdad7d
812 (do not change this comment) */