Trailing whitespace deleted.
[bpt/emacs.git] / src / abbrev.c
CommitLineData
7942b8ae 1/* Primitives for word-abbrev mode.
a97569cb
GM
2 Copyright (C) 1985, 1986, 1993, 1996, 1998, 2001
3 Free Software Foundation, Inc.
7942b8ae
RS
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
c89475dc 9the Free Software Foundation; either version 2, or (at your option)
7942b8ae
RS
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
7942b8ae
RS
21
22
18160b98 23#include <config.h>
7942b8ae 24#include <stdio.h>
7ee72033 25
7942b8ae
RS
26#include "lisp.h"
27#include "commands.h"
28#include "buffer.h"
29#include "window.h"
9192a027 30#include "charset.h"
7169beb1 31#include "syntax.h"
7942b8ae
RS
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
44Lisp_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
49Lisp_Object Vglobal_abbrev_table;
50
51/* The local abbrev table used by default (in Fundamental Mode buffers) */
52
53Lisp_Object Vfundamental_mode_abbrev_table;
54
55/* Set nonzero when an abbrev definition is changed */
56
57int abbrevs_changed;
58
59int 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
64Lisp_Object Vabbrev_start_location;
65
66/* Buffer that Vabbrev_start_location applies to */
67Lisp_Object Vabbrev_start_location_buffer;
68
69/* The symbol representing the abbrev most recently expanded */
70
71Lisp_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
76Lisp_Object Vlast_abbrev_text;
77
78/* Character address of start of last abbrev expanded */
79
31ade731 80EMACS_INT last_abbrev_point;
7942b8ae 81
dbd7a969
RS
82/* Hook to run before expanding any abbrev. */
83
84Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
2d6c1fc0
RS
85
86Lisp_Object Qsystem_type, Qcount;
7942b8ae
RS
87\f
88DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
7ee72033
MB
89 doc: /* Create a new, empty abbrev table object. */)
90 ()
7942b8ae 91{
da2ba5c6 92 /* The value 59 is arbitrary chosen prime number. */
7942b8ae
RS
93 return Fmake_vector (make_number (59), make_number (0));
94}
95
96DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
7ee72033
MB
97 doc: /* Undefine all abbrevs in abbrev table TABLE, leaving it empty. */)
98 (table)
7942b8ae
RS
99 Lisp_Object table;
100{
101 int i, size;
102
b7826503 103 CHECK_VECTOR (table);
7942b8ae
RS
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\f
2d6c1fc0 111DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 6, 0,
7ee72033 112 doc: /* Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.
b39fb64b
PJ
113NAME must be a string.
114EXPANSION should usually be a string.
115To undefine an abbrev, define it with EXPANSION = nil.
116If HOOK is non-nil, it should be a function of no arguments;
117it is called after EXPANSION is inserted.
118If EXPANSION is not a string, the abbrev is a special one,
119 which does not expand in the usual way but only runs HOOK.
2d6c1fc0
RS
120
121COUNT, if specified, gives the initial value for the abbrev's
122usage-count, which is incremented each time the abbrev is used.
123\(The default is zero.)
124
125SYSTEM-FLAG, if non-nil, says that this is a "system" abbreviation
126which should not be saved in the user's abbreviation file. */)
127 (table, name, expansion, hook, count, system_flag)
128 Lisp_Object table, name, expansion, hook, count, system_flag;
7942b8ae
RS
129{
130 Lisp_Object sym, oexp, ohook, tem;
b7826503
PJ
131 CHECK_VECTOR (table);
132 CHECK_STRING (name);
b7734773 133
d427b66a 134 if (NILP (count))
7942b8ae
RS
135 count = make_number (0);
136 else
b7826503 137 CHECK_NUMBER (count);
7942b8ae
RS
138
139 sym = Fintern (name, table);
140
a97569cb 141 oexp = SYMBOL_VALUE (sym);
7942b8ae
RS
142 ohook = XSYMBOL (sym)->function;
143 if (!((EQ (oexp, expansion)
09e82d7c 144 || (STRINGP (oexp) && STRINGP (expansion)
d427b66a 145 && (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
7942b8ae
RS
146 &&
147 (EQ (ohook, hook)
2d6c1fc0
RS
148 || (tem = Fequal (ohook, hook), !NILP (tem))))
149 && NILP (system_flag))
7942b8ae
RS
150 abbrevs_changed = 1;
151
152 Fset (sym, expansion);
153 Ffset (sym, hook);
2d6c1fc0
RS
154
155 if (! NILP (system_flag))
156 Fsetplist (sym, list4 (Qcount, count, Qsystem_type, system_flag));
157 else
158 Fsetplist (sym, count);
7942b8ae
RS
159
160 return name;
161}
162
163DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
b39fb64b 164 "sDefine global abbrev: \nsExpansion for %s: ",
7ee72033
MB
165 doc: /* Define ABBREV as a global abbreviation for EXPANSION. */)
166 (abbrev, expansion)
78ce396a 167 Lisp_Object abbrev, expansion;
7942b8ae 168{
78ce396a 169 Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (abbrev),
2d6c1fc0 170 expansion, Qnil, make_number (0), Qnil);
78ce396a 171 return abbrev;
7942b8ae
RS
172}
173
174DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
b39fb64b 175 "sDefine mode abbrev: \nsExpansion for %s: ",
7ee72033
MB
176 doc: /* Define ABBREV as a mode-specific abbreviation for EXPANSION. */)
177 (abbrev, expansion)
78ce396a 178 Lisp_Object abbrev, expansion;
7942b8ae 179{
d427b66a 180 if (NILP (current_buffer->abbrev_table))
7942b8ae
RS
181 error ("Major mode has no abbrev table");
182
78ce396a 183 Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (abbrev),
2d6c1fc0 184 expansion, Qnil, make_number (0), Qnil);
78ce396a 185 return abbrev;
7942b8ae
RS
186}
187
188DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
7ee72033 189 doc: /* Return the symbol representing abbrev named ABBREV.
b39fb64b
PJ
190This symbol's name is ABBREV, but it is not the canonical symbol of that name;
191it is interned in an abbrev-table rather than the normal obarray.
192The value is nil if that abbrev is not defined.
193Optional second arg TABLE is abbrev table to look it up in.
7ee72033
MB
194The default is to try buffer's mode-specific abbrev table, then global table. */)
195 (abbrev, table)
7942b8ae
RS
196 Lisp_Object abbrev, table;
197{
198 Lisp_Object sym;
b7826503 199 CHECK_STRING (abbrev);
d427b66a 200 if (!NILP (table))
7942b8ae
RS
201 sym = Fintern_soft (abbrev, table);
202 else
203 {
204 sym = Qnil;
d427b66a 205 if (!NILP (current_buffer->abbrev_table))
7942b8ae 206 sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
a97569cb 207 if (NILP (SYMBOL_VALUE (sym)))
7942b8ae 208 sym = Qnil;
d427b66a 209 if (NILP (sym))
7942b8ae
RS
210 sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
211 }
a97569cb
GM
212 if (NILP (SYMBOL_VALUE (sym)))
213 return Qnil;
7942b8ae
RS
214 return sym;
215}
216
217DEFUN ("abbrev-expansion", Fabbrev_expansion, Sabbrev_expansion, 1, 2, 0,
7ee72033 218 doc: /* Return the string that ABBREV expands into in the current buffer.
b39fb64b 219Optionally specify an abbrev table as second arg;
7ee72033
MB
220then ABBREV is looked up in that table only. */)
221 (abbrev, table)
7942b8ae
RS
222 Lisp_Object abbrev, table;
223{
224 Lisp_Object sym;
225 sym = Fabbrev_symbol (abbrev, table);
d427b66a 226 if (NILP (sym)) return sym;
7942b8ae
RS
227 return Fsymbol_value (sym);
228}
229\f
230/* Expand the word before point, if it is an abbrev.
231 Returns 1 if an expansion is done. */
232
233DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
7ee72033 234 doc: /* Expand the abbrev before point, if there is an abbrev there.
b39fb64b 235Effective when explicitly called even when `abbrev-mode' is nil.
7ee72033
MB
236Returns the abbrev symbol, if expansion took place. */)
237 ()
7942b8ae
RS
238{
239 register char *buffer, *p;
aa406bac 240 int wordstart, wordend;
530e0751 241 register int wordstart_byte, wordend_byte, idx, idx_byte;
7942b8ae
RS
242 int whitecnt;
243 int uccount = 0, lccount = 0;
244 register Lisp_Object sym;
245 Lisp_Object expansion, hook, tem;
ba70da8f 246 Lisp_Object value;
530e0751 247 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
7942b8ae 248
f530ce27
RS
249 value = Qnil;
250
6a15331f 251 Frun_hooks (1, &Qpre_abbrev_expand_hook);
dbd7a969 252
dc7e2b30 253 wordstart = 0;
f530ce27
RS
254 if (!(BUFFERP (Vabbrev_start_location_buffer)
255 && XBUFFER (Vabbrev_start_location_buffer) == current_buffer))
7942b8ae 256 Vabbrev_start_location = Qnil;
d427b66a 257 if (!NILP (Vabbrev_start_location))
7942b8ae
RS
258 {
259 tem = Vabbrev_start_location;
b7826503 260 CHECK_NUMBER_COERCE_MARKER (tem);
7942b8ae
RS
261 wordstart = XINT (tem);
262 Vabbrev_start_location = Qnil;
dc7e2b30
KH
263 if (wordstart < BEGV || wordstart > ZV)
264 wordstart = 0;
aa406bac
RS
265 if (wordstart && wordstart != ZV)
266 {
267 wordstart_byte = CHAR_TO_BYTE (wordstart);
268 if (FETCH_BYTE (wordstart_byte) == '-')
269 del_range (wordstart, wordstart + 1);
270 }
7942b8ae 271 }
dc7e2b30 272 if (!wordstart)
6ec8bbd2 273 wordstart = scan_words (PT, -1);
7942b8ae
RS
274
275 if (!wordstart)
ba70da8f 276 return value;
7942b8ae 277
aa406bac 278 wordstart_byte = CHAR_TO_BYTE (wordstart);
7942b8ae
RS
279 wordend = scan_words (wordstart, 1);
280 if (!wordend)
ba70da8f 281 return value;
7942b8ae 282
6ec8bbd2
KH
283 if (wordend > PT)
284 wordend = PT;
aa406bac
RS
285
286 wordend_byte = CHAR_TO_BYTE (wordend);
6ec8bbd2 287 whitecnt = PT - wordend;
7942b8ae 288 if (wordend <= wordstart)
ba70da8f 289 return value;
7942b8ae 290
aa406bac 291 p = buffer = (char *) alloca (wordend_byte - wordstart_byte);
7942b8ae 292
530e0751 293 for (idx = wordstart, idx_byte = wordstart_byte; idx < wordend; )
7942b8ae 294 {
530e0751
KH
295 register int c;
296
297 if (multibyte)
298 {
299 FETCH_CHAR_ADVANCE (c, idx, idx_byte);
300 }
301 else
302 {
303 c = FETCH_BYTE (idx_byte);
304 idx++, idx_byte++;
305 }
306
7942b8ae
RS
307 if (UPPERCASEP (c))
308 c = DOWNCASE (c), uccount++;
309 else if (! NOCASEP (c))
310 lccount++;
530e0751
KH
311 if (multibyte)
312 p += CHAR_STRING (c, p);
313 else
314 *p++ = c;
7942b8ae
RS
315 }
316
09e82d7c 317 if (VECTORP (current_buffer->abbrev_table))
fc412686 318 sym = oblookup (current_buffer->abbrev_table, buffer,
530e0751 319 wordend - wordstart, p - buffer);
7942b8ae 320 else
2a43e2bc 321 XSETFASTINT (sym, 0);
2d6c1fc0 322
a97569cb 323 if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym)))
fc412686 324 sym = oblookup (Vglobal_abbrev_table, buffer,
530e0751 325 wordend - wordstart, p - buffer);
a97569cb 326 if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym)))
ba70da8f 327 return value;
7942b8ae
RS
328
329 if (INTERACTIVE && !EQ (minibuf_window, selected_window))
330 {
aba686ed
RS
331 /* Add an undo boundary, in case we are doing this for
332 a self-inserting command which has avoided making one so far. */
7942b8ae
RS
333 SET_PT (wordend);
334 Fundo_boundary ();
335 }
b7734773 336
7942b8ae
RS
337 Vlast_abbrev_text
338 = Fbuffer_substring (make_number (wordstart), make_number (wordend));
7942b8ae 339
b7734773 340 /* Now sym is the abbrev symbol. */
7942b8ae 341 Vlast_abbrev = sym;
f530ce27 342 value = sym;
7942b8ae
RS
343 last_abbrev_point = wordstart;
344
2d6c1fc0 345 /* Increment use count. */
09e82d7c 346 if (INTEGERP (XSYMBOL (sym)->plist))
7942b8ae 347 XSETINT (XSYMBOL (sym)->plist,
2d6c1fc0 348 XINT (XSYMBOL (sym)->plist) + 1);
8d320872 349 else if (INTEGERP (tem = Fget (sym, Qcount)))
2d6c1fc0 350 Fput (sym, Qcount, make_number (XINT (tem) + 1));
7942b8ae 351
b7734773
RS
352 /* If this abbrev has an expansion, delete the abbrev
353 and insert the expansion. */
a97569cb 354 expansion = SYMBOL_VALUE (sym);
b7734773 355 if (STRINGP (expansion))
7942b8ae 356 {
b7734773
RS
357 SET_PT (wordstart);
358
bc69581b 359 del_range_both (wordstart, wordstart_byte, wordend, wordend_byte, 1);
b7734773 360
d5db4077
KR
361 insert_from_string (expansion, 0, 0, SCHARS (expansion),
362 SBYTES (expansion), 1);
b7734773
RS
363 SET_PT (PT + whitecnt);
364
365 if (uccount && !lccount)
366 {
367 /* Abbrev was all caps */
368 /* If expansion is multiple words, normally capitalize each word */
369 /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
370 but Megatest 68000 compiler can't handle that */
371 if (!abbrev_all_caps)
372 if (scan_words (PT, -1) > scan_words (wordstart, 1))
373 {
374 Fupcase_initials_region (make_number (wordstart),
375 make_number (PT));
376 goto caped;
377 }
378 /* If expansion is one word, or if user says so, upcase it all. */
379 Fupcase_region (make_number (wordstart), make_number (PT));
380 caped: ;
381 }
382 else if (uccount)
383 {
384 /* Abbrev included some caps. Cap first initial of expansion */
aa406bac 385 int pos = wordstart_byte;
b7734773
RS
386
387 /* Find the initial. */
aa406bac
RS
388 while (pos < PT_BYTE
389 && SYNTAX (*BUF_BYTE_ADDRESS (current_buffer, pos)) != Sword)
b7734773
RS
390 pos++;
391
392 /* Change just that. */
aa406bac 393 pos = BYTE_TO_CHAR (pos);
b7734773
RS
394 Fupcase_initials_region (make_number (pos), make_number (pos + 1));
395 }
7942b8ae
RS
396 }
397
398 hook = XSYMBOL (sym)->function;
d427b66a 399 if (!NILP (hook))
79d2af9c
GM
400 {
401 Lisp_Object expanded, prop;
402
c87dbfd0 403 /* If the abbrev has a hook function, run it. */
79d2af9c 404 expanded = call0 (hook);
c87dbfd0 405
ca70e62f
PJ
406 /* In addition, if the hook function is a symbol with
407 a non-nil `no-self-insert' property, let the value it returned
c87dbfd0
RS
408 specify whether we consider that an expansion took place. If
409 it returns nil, no expansion has been done. */
410
79d2af9c
GM
411 if (SYMBOLP (hook)
412 && NILP (expanded)
413 && (prop = Fget (hook, intern ("no-self-insert")),
414 !NILP (prop)))
415 value = Qnil;
416 }
7942b8ae 417
f530ce27 418 return value;
7942b8ae
RS
419}
420
421DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
7ee72033 422 doc: /* Undo the expansion of the last abbrev that expanded.
b39fb64b 423This differs from ordinary undo in that other editing done since then
7ee72033
MB
424is not undone. */)
425 ()
7942b8ae 426{
6ec8bbd2 427 int opoint = PT;
7942b8ae
RS
428 int adjust = 0;
429 if (last_abbrev_point < BEGV
430 || last_abbrev_point > ZV)
431 return Qnil;
432 SET_PT (last_abbrev_point);
09e82d7c 433 if (STRINGP (Vlast_abbrev_text))
7942b8ae
RS
434 {
435 /* This isn't correct if Vlast_abbrev->function was used
436 to do the expansion */
437 Lisp_Object val;
aa406bac
RS
438 int zv_before;
439
a97569cb 440 val = SYMBOL_VALUE (Vlast_abbrev);
09e82d7c 441 if (!STRINGP (val))
4458687c 442 error ("value of abbrev-symbol must be a string");
aa406bac 443 zv_before = ZV;
d5db4077 444 del_range_byte (PT_BYTE, PT_BYTE + SBYTES (val), 1);
0c287112 445 /* Don't inherit properties here; just copy from old contents. */
fc412686 446 insert_from_string (Vlast_abbrev_text, 0, 0,
d5db4077
KR
447 SCHARS (Vlast_abbrev_text),
448 SBYTES (Vlast_abbrev_text), 0);
7942b8ae 449 Vlast_abbrev_text = Qnil;
aa406bac
RS
450 /* Total number of characters deleted. */
451 adjust = ZV - zv_before;
7942b8ae 452 }
57522629 453 SET_PT (last_abbrev_point < opoint ? opoint + adjust : opoint);
7942b8ae
RS
454 return Qnil;
455}
456\f
aa406bac 457static void
7942b8ae
RS
458write_abbrev (sym, stream)
459 Lisp_Object sym, stream;
460{
2d6c1fc0
RS
461 Lisp_Object name, count, system_flag;
462
463 if (INTEGERP (XSYMBOL (sym)->plist))
464 {
465 count = XSYMBOL (sym)->plist;
466 system_flag = Qnil;
467 }
468 else
469 {
470 count = Fget (sym, Qcount);
471 system_flag = Fget (sym, Qsystem_type);
472 }
473
474 if (NILP (SYMBOL_VALUE (sym)) || ! NILP (system_flag))
7942b8ae 475 return;
2d6c1fc0 476
7942b8ae 477 insert (" (", 5);
caeead20 478 name = SYMBOL_NAME (sym);
7942b8ae
RS
479 Fprin1 (name, stream);
480 insert (" ", 1);
a97569cb 481 Fprin1 (SYMBOL_VALUE (sym), stream);
7942b8ae
RS
482 insert (" ", 1);
483 Fprin1 (XSYMBOL (sym)->function, stream);
484 insert (" ", 1);
2d6c1fc0 485 Fprin1 (count, stream);
7942b8ae
RS
486 insert (")\n", 2);
487}
488
aa406bac 489static void
7942b8ae
RS
490describe_abbrev (sym, stream)
491 Lisp_Object sym, stream;
492{
2d6c1fc0
RS
493 Lisp_Object one, count, system_flag;
494
495 if (INTEGERP (XSYMBOL (sym)->plist))
496 {
497 count = XSYMBOL (sym)->plist;
498 system_flag = Qnil;
499 }
500 else
501 {
502 count = Fget (sym, Qcount);
503 system_flag = Fget (sym, Qsystem_type);
504 }
7942b8ae 505
a97569cb 506 if (NILP (SYMBOL_VALUE (sym)))
7942b8ae 507 return;
2d6c1fc0 508
7942b8ae
RS
509 one = make_number (1);
510 Fprin1 (Fsymbol_name (sym), stream);
2d6c1fc0
RS
511
512 if (!NILP (system_flag))
513 {
514 insert_string (" (sys)");
515 Findent_to (make_number (20), one);
516 }
517 else
518 Findent_to (make_number (15), one);
519
520 Fprin1 (count, stream);
7942b8ae 521 Findent_to (make_number (20), one);
a97569cb 522 Fprin1 (SYMBOL_VALUE (sym), stream);
d427b66a 523 if (!NILP (XSYMBOL (sym)->function))
7942b8ae
RS
524 {
525 Findent_to (make_number (45), one);
526 Fprin1 (XSYMBOL (sym)->function, stream);
527 }
528 Fterpri (stream);
529}
530
a0d76c27 531DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,
03be2694 532 Sinsert_abbrev_table_description, 1, 2, 0,
7ee72033 533 doc: /* Insert before point a full description of abbrev table named NAME.
b39fb64b
PJ
534NAME is a symbol whose value is an abbrev table.
535If optional 2nd arg READABLE is non-nil, a human-readable description
536is inserted. Otherwise the description is an expression,
537a call to `define-abbrev-table', which would
2d6c1fc0
RS
538define the abbrev table NAME exactly as it is currently defined.
539
540Abbrevs marked as "system abbrevs" are omitted. */)
7ee72033 541 (name, readable)
7942b8ae
RS
542 Lisp_Object name, readable;
543{
544 Lisp_Object table;
545 Lisp_Object stream;
546
b7826503 547 CHECK_SYMBOL (name);
7942b8ae 548 table = Fsymbol_value (name);
b7826503 549 CHECK_VECTOR (table);
7942b8ae 550
6520d056 551 XSETBUFFER (stream, current_buffer);
7942b8ae 552
d427b66a 553 if (!NILP (readable))
7942b8ae
RS
554 {
555 insert_string ("(");
556 Fprin1 (name, stream);
557 insert_string (")\n\n");
558 map_obarray (table, describe_abbrev, stream);
559 insert_string ("\n\n");
560 }
561 else
562 {
563 insert_string ("(define-abbrev-table '");
564 Fprin1 (name, stream);
565 insert_string (" '(\n");
566 map_obarray (table, write_abbrev, stream);
567 insert_string (" ))\n\n");
568 }
569
570 return Qnil;
571}
572\f
573DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
574 2, 2, 0,
7ee72033 575 doc: /* Define TABLENAME (a symbol) as an abbrev table name.
b39fb64b 576Define abbrevs in it according to DEFINITIONS, which is a list of elements
2d6c1fc0
RS
577of the form (ABBREVNAME EXPANSION HOOK USECOUNT SYSTEMFLAG).
578\(If the list is shorter than that, omitted elements default to nil). */)
7ee72033 579 (tablename, definitions)
b9d613cc 580 Lisp_Object tablename, definitions;
7942b8ae
RS
581{
582 Lisp_Object name, exp, hook, count;
2d6c1fc0 583 Lisp_Object table, elt, sys;
7942b8ae 584
b7826503 585 CHECK_SYMBOL (tablename);
78ce396a
EN
586 table = Fboundp (tablename);
587 if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
7942b8ae
RS
588 {
589 table = Fmake_abbrev_table ();
78ce396a 590 Fset (tablename, table);
b9d613cc 591 Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
7942b8ae 592 }
b7826503 593 CHECK_VECTOR (table);
7942b8ae 594
b9d613cc 595 for (; !NILP (definitions); definitions = Fcdr (definitions))
7942b8ae 596 {
78ce396a 597 elt = Fcar (definitions);
0292bcb1
JB
598 name = Fcar (elt); elt = Fcdr (elt);
599 exp = Fcar (elt); elt = Fcdr (elt);
600 hook = Fcar (elt); elt = Fcdr (elt);
2d6c1fc0
RS
601 count = Fcar (elt); elt = Fcdr (elt);
602 sys = Fcar (elt);
603 Fdefine_abbrev (table, name, exp, hook, count, sys);
7942b8ae
RS
604 }
605 return Qnil;
606}
607\f
dfcf069d 608void
7942b8ae
RS
609syms_of_abbrev ()
610{
2d6c1fc0
RS
611 Qsystem_type = intern ("system-type");
612 staticpro (&Qsystem_type);
613
614 Qcount = intern ("count");
615 staticpro (&Qcount);
616
7ee72033
MB
617 DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
618 doc: /* List of symbols whose values are abbrev tables. */);
7942b8ae
RS
619 Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
620 Fcons (intern ("global-abbrev-table"),
621 Qnil));
622
7ee72033
MB
623 DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
624 doc: /* The abbrev table whose abbrevs affect all buffers.
b39fb64b
PJ
625Each buffer may also have a local abbrev table.
626If it does, the local table overrides the global one
627for any particular abbrev defined in both. */);
7942b8ae
RS
628 Vglobal_abbrev_table = Fmake_abbrev_table ();
629
7ee72033
MB
630 DEFVAR_LISP ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
631 doc: /* The abbrev table of mode-specific abbrevs for Fundamental Mode. */);
7942b8ae
RS
632 Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
633 current_buffer->abbrev_table = Vfundamental_mode_abbrev_table;
c8bb8167 634 buffer_defaults.abbrev_table = Vfundamental_mode_abbrev_table;
7942b8ae 635
7ee72033
MB
636 DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
637 doc: /* The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'. */);
7942b8ae 638
7ee72033
MB
639 DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
640 doc: /* The exact text of the last abbrev expanded.
b39fb64b 641nil if the abbrev has already been unexpanded. */);
7942b8ae 642
7ee72033
MB
643 DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
644 doc: /* The location of the start of the last abbrev expanded. */);
7942b8ae
RS
645
646 Vlast_abbrev = Qnil;
647 Vlast_abbrev_text = Qnil;
648 last_abbrev_point = 0;
649
7ee72033
MB
650 DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
651 doc: /* Buffer position for `expand-abbrev' to use as the start of the abbrev.
ca70e62f 652When nil, use the word before point as the abbrev.
b39fb64b 653Calling `expand-abbrev' sets this to nil. */);
7942b8ae
RS
654 Vabbrev_start_location = Qnil;
655
7ee72033
MB
656 DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
657 doc: /* Buffer that `abbrev-start-location' has been set for.
b39fb64b 658Trying to expand an abbrev in any other buffer clears `abbrev-start-location'. */);
7942b8ae
RS
659 Vabbrev_start_location_buffer = Qnil;
660
7ee72033
MB
661 DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
662 doc: /* Local (mode-specific) abbrev table of current buffer. */);
7942b8ae 663
7ee72033
MB
664 DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
665 doc: /* Set non-nil by defining or altering any word abbrevs.
b39fb64b 666This causes `save-some-buffers' to offer to save the abbrevs. */);
7942b8ae
RS
667 abbrevs_changed = 0;
668
7ee72033
MB
669 DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
670 doc: /* *Set non-nil means expand multi-word abbrevs all caps if abbrev was so. */);
7942b8ae
RS
671 abbrev_all_caps = 0;
672
7ee72033
MB
673 DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
674 doc: /* Function or functions to be called before abbrev expansion is done.
b39fb64b
PJ
675This is the first thing that `expand-abbrev' does, and so this may change
676the current abbrev table before abbrev lookup happens. */);
dbd7a969
RS
677 Vpre_abbrev_expand_hook = Qnil;
678 Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
679 staticpro (&Qpre_abbrev_expand_hook);
680
7942b8ae
RS
681 defsubr (&Smake_abbrev_table);
682 defsubr (&Sclear_abbrev_table);
683 defsubr (&Sdefine_abbrev);
684 defsubr (&Sdefine_global_abbrev);
685 defsubr (&Sdefine_mode_abbrev);
686 defsubr (&Sabbrev_expansion);
687 defsubr (&Sabbrev_symbol);
688 defsubr (&Sexpand_abbrev);
689 defsubr (&Sunexpand_abbrev);
690 defsubr (&Sinsert_abbrev_table_description);
691 defsubr (&Sdefine_abbrev_table);
692}