Update FSF's address.
[bpt/emacs.git] / src / abbrev.c
CommitLineData
7942b8ae 1/* Primitives for word-abbrev mode.
a0ecb2ac 2 Copyright (C) 1985, 1986, 1993, 1996, 1998, 2001,02,03,04
a97569cb 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
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, 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
451eaa21
RS
251 Frun_hooks (1, &Qpre_abbrev_expand_hook);
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 }
177c0ea7 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
d5db4077
KR
359 insert_from_string (expansion, 0, 0, SCHARS (expansion),
360 SBYTES (expansion), 1);
f8f096e9
RS
361 del_range_both (PT, PT_BYTE,
362 wordend + (PT - wordstart),
363 wordend_byte + (PT_BYTE - wordstart_byte),
364 1);
365
b7734773
RS
366 SET_PT (PT + whitecnt);
367
368 if (uccount && !lccount)
369 {
370 /* Abbrev was all caps */
371 /* If expansion is multiple words, normally capitalize each word */
372 /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
373 but Megatest 68000 compiler can't handle that */
374 if (!abbrev_all_caps)
375 if (scan_words (PT, -1) > scan_words (wordstart, 1))
376 {
377 Fupcase_initials_region (make_number (wordstart),
378 make_number (PT));
379 goto caped;
380 }
381 /* If expansion is one word, or if user says so, upcase it all. */
382 Fupcase_region (make_number (wordstart), make_number (PT));
383 caped: ;
384 }
385 else if (uccount)
386 {
387 /* Abbrev included some caps. Cap first initial of expansion */
aa406bac 388 int pos = wordstart_byte;
b7734773
RS
389
390 /* Find the initial. */
aa406bac
RS
391 while (pos < PT_BYTE
392 && SYNTAX (*BUF_BYTE_ADDRESS (current_buffer, pos)) != Sword)
b7734773
RS
393 pos++;
394
395 /* Change just that. */
aa406bac 396 pos = BYTE_TO_CHAR (pos);
b7734773
RS
397 Fupcase_initials_region (make_number (pos), make_number (pos + 1));
398 }
7942b8ae
RS
399 }
400
401 hook = XSYMBOL (sym)->function;
d427b66a 402 if (!NILP (hook))
79d2af9c
GM
403 {
404 Lisp_Object expanded, prop;
405
c87dbfd0 406 /* If the abbrev has a hook function, run it. */
79d2af9c 407 expanded = call0 (hook);
c87dbfd0 408
ca70e62f
PJ
409 /* In addition, if the hook function is a symbol with
410 a non-nil `no-self-insert' property, let the value it returned
c87dbfd0
RS
411 specify whether we consider that an expansion took place. If
412 it returns nil, no expansion has been done. */
413
79d2af9c
GM
414 if (SYMBOLP (hook)
415 && NILP (expanded)
416 && (prop = Fget (hook, intern ("no-self-insert")),
417 !NILP (prop)))
418 value = Qnil;
419 }
7942b8ae 420
f530ce27 421 return value;
7942b8ae
RS
422}
423
424DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
7ee72033 425 doc: /* Undo the expansion of the last abbrev that expanded.
b39fb64b 426This differs from ordinary undo in that other editing done since then
7ee72033
MB
427is not undone. */)
428 ()
7942b8ae 429{
6ec8bbd2 430 int opoint = PT;
7942b8ae
RS
431 int adjust = 0;
432 if (last_abbrev_point < BEGV
433 || last_abbrev_point > ZV)
434 return Qnil;
435 SET_PT (last_abbrev_point);
09e82d7c 436 if (STRINGP (Vlast_abbrev_text))
7942b8ae
RS
437 {
438 /* This isn't correct if Vlast_abbrev->function was used
439 to do the expansion */
440 Lisp_Object val;
aa406bac
RS
441 int zv_before;
442
a97569cb 443 val = SYMBOL_VALUE (Vlast_abbrev);
09e82d7c 444 if (!STRINGP (val))
d4db983a 445 error ("Value of `abbrev-symbol' must be a string");
aa406bac 446 zv_before = ZV;
d5db4077 447 del_range_byte (PT_BYTE, PT_BYTE + SBYTES (val), 1);
0c287112 448 /* Don't inherit properties here; just copy from old contents. */
fc412686 449 insert_from_string (Vlast_abbrev_text, 0, 0,
d5db4077
KR
450 SCHARS (Vlast_abbrev_text),
451 SBYTES (Vlast_abbrev_text), 0);
7942b8ae 452 Vlast_abbrev_text = Qnil;
aa406bac
RS
453 /* Total number of characters deleted. */
454 adjust = ZV - zv_before;
7942b8ae 455 }
57522629 456 SET_PT (last_abbrev_point < opoint ? opoint + adjust : opoint);
7942b8ae
RS
457 return Qnil;
458}
459\f
aa406bac 460static void
7942b8ae
RS
461write_abbrev (sym, stream)
462 Lisp_Object sym, stream;
463{
2d6c1fc0
RS
464 Lisp_Object name, count, system_flag;
465
466 if (INTEGERP (XSYMBOL (sym)->plist))
467 {
468 count = XSYMBOL (sym)->plist;
469 system_flag = Qnil;
470 }
471 else
472 {
473 count = Fget (sym, Qcount);
474 system_flag = Fget (sym, Qsystem_type);
475 }
476
477 if (NILP (SYMBOL_VALUE (sym)) || ! NILP (system_flag))
7942b8ae 478 return;
2d6c1fc0 479
7942b8ae 480 insert (" (", 5);
caeead20 481 name = SYMBOL_NAME (sym);
7942b8ae
RS
482 Fprin1 (name, stream);
483 insert (" ", 1);
a97569cb 484 Fprin1 (SYMBOL_VALUE (sym), stream);
7942b8ae
RS
485 insert (" ", 1);
486 Fprin1 (XSYMBOL (sym)->function, stream);
487 insert (" ", 1);
2d6c1fc0 488 Fprin1 (count, stream);
7942b8ae
RS
489 insert (")\n", 2);
490}
491
aa406bac 492static void
7942b8ae
RS
493describe_abbrev (sym, stream)
494 Lisp_Object sym, stream;
495{
2d6c1fc0
RS
496 Lisp_Object one, count, system_flag;
497
498 if (INTEGERP (XSYMBOL (sym)->plist))
499 {
500 count = XSYMBOL (sym)->plist;
501 system_flag = Qnil;
502 }
503 else
504 {
505 count = Fget (sym, Qcount);
506 system_flag = Fget (sym, Qsystem_type);
507 }
7942b8ae 508
a97569cb 509 if (NILP (SYMBOL_VALUE (sym)))
7942b8ae 510 return;
2d6c1fc0 511
7942b8ae
RS
512 one = make_number (1);
513 Fprin1 (Fsymbol_name (sym), stream);
2d6c1fc0
RS
514
515 if (!NILP (system_flag))
516 {
517 insert_string (" (sys)");
518 Findent_to (make_number (20), one);
519 }
520 else
521 Findent_to (make_number (15), one);
522
523 Fprin1 (count, stream);
7942b8ae 524 Findent_to (make_number (20), one);
a97569cb 525 Fprin1 (SYMBOL_VALUE (sym), stream);
d427b66a 526 if (!NILP (XSYMBOL (sym)->function))
7942b8ae
RS
527 {
528 Findent_to (make_number (45), one);
529 Fprin1 (XSYMBOL (sym)->function, stream);
530 }
531 Fterpri (stream);
532}
533
a0d76c27 534DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,
03be2694 535 Sinsert_abbrev_table_description, 1, 2, 0,
7ee72033 536 doc: /* Insert before point a full description of abbrev table named NAME.
b39fb64b
PJ
537NAME is a symbol whose value is an abbrev table.
538If optional 2nd arg READABLE is non-nil, a human-readable description
539is inserted. Otherwise the description is an expression,
540a call to `define-abbrev-table', which would
2d6c1fc0
RS
541define the abbrev table NAME exactly as it is currently defined.
542
7f144ff5
LT
543Abbrevs marked as "system abbrevs" are normally omitted. However, if
544READABLE is non-nil, they are listed. */)
7ee72033 545 (name, readable)
7942b8ae
RS
546 Lisp_Object name, readable;
547{
548 Lisp_Object table;
549 Lisp_Object stream;
550
b7826503 551 CHECK_SYMBOL (name);
7942b8ae 552 table = Fsymbol_value (name);
b7826503 553 CHECK_VECTOR (table);
7942b8ae 554
6520d056 555 XSETBUFFER (stream, current_buffer);
7942b8ae 556
d427b66a 557 if (!NILP (readable))
7942b8ae
RS
558 {
559 insert_string ("(");
560 Fprin1 (name, stream);
561 insert_string (")\n\n");
562 map_obarray (table, describe_abbrev, stream);
563 insert_string ("\n\n");
564 }
565 else
566 {
567 insert_string ("(define-abbrev-table '");
568 Fprin1 (name, stream);
569 insert_string (" '(\n");
570 map_obarray (table, write_abbrev, stream);
571 insert_string (" ))\n\n");
572 }
573
574 return Qnil;
575}
576\f
577DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
578 2, 2, 0,
7ee72033 579 doc: /* Define TABLENAME (a symbol) as an abbrev table name.
b39fb64b 580Define abbrevs in it according to DEFINITIONS, which is a list of elements
2d6c1fc0
RS
581of the form (ABBREVNAME EXPANSION HOOK USECOUNT SYSTEMFLAG).
582\(If the list is shorter than that, omitted elements default to nil). */)
7ee72033 583 (tablename, definitions)
b9d613cc 584 Lisp_Object tablename, definitions;
7942b8ae
RS
585{
586 Lisp_Object name, exp, hook, count;
2d6c1fc0 587 Lisp_Object table, elt, sys;
7942b8ae 588
b7826503 589 CHECK_SYMBOL (tablename);
78ce396a
EN
590 table = Fboundp (tablename);
591 if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
7942b8ae
RS
592 {
593 table = Fmake_abbrev_table ();
78ce396a 594 Fset (tablename, table);
b9d613cc 595 Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
7942b8ae 596 }
b7826503 597 CHECK_VECTOR (table);
7942b8ae 598
52ad5ecc 599 for (; CONSP (definitions); definitions = XCDR (definitions))
7942b8ae 600 {
52ad5ecc 601 elt = XCAR (definitions);
0292bcb1
JB
602 name = Fcar (elt); elt = Fcdr (elt);
603 exp = Fcar (elt); elt = Fcdr (elt);
604 hook = Fcar (elt); elt = Fcdr (elt);
2d6c1fc0
RS
605 count = Fcar (elt); elt = Fcdr (elt);
606 sys = Fcar (elt);
607 Fdefine_abbrev (table, name, exp, hook, count, sys);
7942b8ae
RS
608 }
609 return Qnil;
610}
611\f
dfcf069d 612void
7942b8ae
RS
613syms_of_abbrev ()
614{
2d6c1fc0
RS
615 Qsystem_type = intern ("system-type");
616 staticpro (&Qsystem_type);
617
618 Qcount = intern ("count");
619 staticpro (&Qcount);
620
7ee72033
MB
621 DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
622 doc: /* List of symbols whose values are abbrev tables. */);
7942b8ae
RS
623 Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
624 Fcons (intern ("global-abbrev-table"),
625 Qnil));
626
7ee72033
MB
627 DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
628 doc: /* The abbrev table whose abbrevs affect all buffers.
b39fb64b
PJ
629Each buffer may also have a local abbrev table.
630If it does, the local table overrides the global one
631for any particular abbrev defined in both. */);
7942b8ae
RS
632 Vglobal_abbrev_table = Fmake_abbrev_table ();
633
7ee72033
MB
634 DEFVAR_LISP ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
635 doc: /* The abbrev table of mode-specific abbrevs for Fundamental Mode. */);
7942b8ae
RS
636 Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
637 current_buffer->abbrev_table = Vfundamental_mode_abbrev_table;
c8bb8167 638 buffer_defaults.abbrev_table = Vfundamental_mode_abbrev_table;
7942b8ae 639
7ee72033
MB
640 DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
641 doc: /* The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'. */);
7942b8ae 642
7ee72033
MB
643 DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
644 doc: /* The exact text of the last abbrev expanded.
b39fb64b 645nil if the abbrev has already been unexpanded. */);
7942b8ae 646
7ee72033
MB
647 DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
648 doc: /* The location of the start of the last abbrev expanded. */);
7942b8ae
RS
649
650 Vlast_abbrev = Qnil;
651 Vlast_abbrev_text = Qnil;
652 last_abbrev_point = 0;
653
7ee72033
MB
654 DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
655 doc: /* Buffer position for `expand-abbrev' to use as the start of the abbrev.
ca70e62f 656When nil, use the word before point as the abbrev.
b39fb64b 657Calling `expand-abbrev' sets this to nil. */);
7942b8ae
RS
658 Vabbrev_start_location = Qnil;
659
7ee72033
MB
660 DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
661 doc: /* Buffer that `abbrev-start-location' has been set for.
b39fb64b 662Trying to expand an abbrev in any other buffer clears `abbrev-start-location'. */);
7942b8ae
RS
663 Vabbrev_start_location_buffer = Qnil;
664
7ee72033
MB
665 DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
666 doc: /* Local (mode-specific) abbrev table of current buffer. */);
7942b8ae 667
7ee72033
MB
668 DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
669 doc: /* Set non-nil by defining or altering any word abbrevs.
b39fb64b 670This causes `save-some-buffers' to offer to save the abbrevs. */);
7942b8ae
RS
671 abbrevs_changed = 0;
672
7ee72033
MB
673 DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
674 doc: /* *Set non-nil means expand multi-word abbrevs all caps if abbrev was so. */);
7942b8ae
RS
675 abbrev_all_caps = 0;
676
7ee72033
MB
677 DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
678 doc: /* Function or functions to be called before abbrev expansion is done.
b39fb64b
PJ
679This is the first thing that `expand-abbrev' does, and so this may change
680the current abbrev table before abbrev lookup happens. */);
dbd7a969
RS
681 Vpre_abbrev_expand_hook = Qnil;
682 Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
683 staticpro (&Qpre_abbrev_expand_hook);
684
7942b8ae
RS
685 defsubr (&Smake_abbrev_table);
686 defsubr (&Sclear_abbrev_table);
687 defsubr (&Sdefine_abbrev);
688 defsubr (&Sdefine_global_abbrev);
689 defsubr (&Sdefine_mode_abbrev);
690 defsubr (&Sabbrev_expansion);
691 defsubr (&Sabbrev_symbol);
692 defsubr (&Sexpand_abbrev);
693 defsubr (&Sunexpand_abbrev);
694 defsubr (&Sinsert_abbrev_table_description);
695 defsubr (&Sdefine_abbrev_table);
696}
ab5796a9
MB
697
698/* arch-tag: b721db69-f633-44a8-a361-c275acbdad7d
699 (do not change this comment) */