Add arch taglines
[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 }
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))
4458687c 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
543Abbrevs marked as "system abbrevs" are omitted. */)
7ee72033 544 (name, readable)
7942b8ae
RS
545 Lisp_Object name, readable;
546{
547 Lisp_Object table;
548 Lisp_Object stream;
549
b7826503 550 CHECK_SYMBOL (name);
7942b8ae 551 table = Fsymbol_value (name);
b7826503 552 CHECK_VECTOR (table);
7942b8ae 553
6520d056 554 XSETBUFFER (stream, current_buffer);
7942b8ae 555
d427b66a 556 if (!NILP (readable))
7942b8ae
RS
557 {
558 insert_string ("(");
559 Fprin1 (name, stream);
560 insert_string (")\n\n");
561 map_obarray (table, describe_abbrev, stream);
562 insert_string ("\n\n");
563 }
564 else
565 {
566 insert_string ("(define-abbrev-table '");
567 Fprin1 (name, stream);
568 insert_string (" '(\n");
569 map_obarray (table, write_abbrev, stream);
570 insert_string (" ))\n\n");
571 }
572
573 return Qnil;
574}
575\f
576DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
577 2, 2, 0,
7ee72033 578 doc: /* Define TABLENAME (a symbol) as an abbrev table name.
b39fb64b 579Define abbrevs in it according to DEFINITIONS, which is a list of elements
2d6c1fc0
RS
580of the form (ABBREVNAME EXPANSION HOOK USECOUNT SYSTEMFLAG).
581\(If the list is shorter than that, omitted elements default to nil). */)
7ee72033 582 (tablename, definitions)
b9d613cc 583 Lisp_Object tablename, definitions;
7942b8ae
RS
584{
585 Lisp_Object name, exp, hook, count;
2d6c1fc0 586 Lisp_Object table, elt, sys;
7942b8ae 587
b7826503 588 CHECK_SYMBOL (tablename);
78ce396a
EN
589 table = Fboundp (tablename);
590 if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
7942b8ae
RS
591 {
592 table = Fmake_abbrev_table ();
78ce396a 593 Fset (tablename, table);
b9d613cc 594 Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
7942b8ae 595 }
b7826503 596 CHECK_VECTOR (table);
7942b8ae 597
52ad5ecc 598 for (; CONSP (definitions); definitions = XCDR (definitions))
7942b8ae 599 {
52ad5ecc 600 elt = XCAR (definitions);
0292bcb1
JB
601 name = Fcar (elt); elt = Fcdr (elt);
602 exp = Fcar (elt); elt = Fcdr (elt);
603 hook = Fcar (elt); elt = Fcdr (elt);
2d6c1fc0
RS
604 count = Fcar (elt); elt = Fcdr (elt);
605 sys = Fcar (elt);
606 Fdefine_abbrev (table, name, exp, hook, count, sys);
7942b8ae
RS
607 }
608 return Qnil;
609}
610\f
dfcf069d 611void
7942b8ae
RS
612syms_of_abbrev ()
613{
2d6c1fc0
RS
614 Qsystem_type = intern ("system-type");
615 staticpro (&Qsystem_type);
616
617 Qcount = intern ("count");
618 staticpro (&Qcount);
619
7ee72033
MB
620 DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
621 doc: /* List of symbols whose values are abbrev tables. */);
7942b8ae
RS
622 Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
623 Fcons (intern ("global-abbrev-table"),
624 Qnil));
625
7ee72033
MB
626 DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
627 doc: /* The abbrev table whose abbrevs affect all buffers.
b39fb64b
PJ
628Each buffer may also have a local abbrev table.
629If it does, the local table overrides the global one
630for any particular abbrev defined in both. */);
7942b8ae
RS
631 Vglobal_abbrev_table = Fmake_abbrev_table ();
632
7ee72033
MB
633 DEFVAR_LISP ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
634 doc: /* The abbrev table of mode-specific abbrevs for Fundamental Mode. */);
7942b8ae
RS
635 Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
636 current_buffer->abbrev_table = Vfundamental_mode_abbrev_table;
c8bb8167 637 buffer_defaults.abbrev_table = Vfundamental_mode_abbrev_table;
7942b8ae 638
7ee72033
MB
639 DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
640 doc: /* The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'. */);
7942b8ae 641
7ee72033
MB
642 DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
643 doc: /* The exact text of the last abbrev expanded.
b39fb64b 644nil if the abbrev has already been unexpanded. */);
7942b8ae 645
7ee72033
MB
646 DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
647 doc: /* The location of the start of the last abbrev expanded. */);
7942b8ae
RS
648
649 Vlast_abbrev = Qnil;
650 Vlast_abbrev_text = Qnil;
651 last_abbrev_point = 0;
652
7ee72033
MB
653 DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
654 doc: /* Buffer position for `expand-abbrev' to use as the start of the abbrev.
ca70e62f 655When nil, use the word before point as the abbrev.
b39fb64b 656Calling `expand-abbrev' sets this to nil. */);
7942b8ae
RS
657 Vabbrev_start_location = Qnil;
658
7ee72033
MB
659 DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
660 doc: /* Buffer that `abbrev-start-location' has been set for.
b39fb64b 661Trying to expand an abbrev in any other buffer clears `abbrev-start-location'. */);
7942b8ae
RS
662 Vabbrev_start_location_buffer = Qnil;
663
7ee72033
MB
664 DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
665 doc: /* Local (mode-specific) abbrev table of current buffer. */);
7942b8ae 666
7ee72033
MB
667 DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
668 doc: /* Set non-nil by defining or altering any word abbrevs.
b39fb64b 669This causes `save-some-buffers' to offer to save the abbrevs. */);
7942b8ae
RS
670 abbrevs_changed = 0;
671
7ee72033
MB
672 DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
673 doc: /* *Set non-nil means expand multi-word abbrevs all caps if abbrev was so. */);
7942b8ae
RS
674 abbrev_all_caps = 0;
675
7ee72033
MB
676 DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
677 doc: /* Function or functions to be called before abbrev expansion is done.
b39fb64b
PJ
678This is the first thing that `expand-abbrev' does, and so this may change
679the current abbrev table before abbrev lookup happens. */);
dbd7a969
RS
680 Vpre_abbrev_expand_hook = Qnil;
681 Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
682 staticpro (&Qpre_abbrev_expand_hook);
683
7942b8ae
RS
684 defsubr (&Smake_abbrev_table);
685 defsubr (&Sclear_abbrev_table);
686 defsubr (&Sdefine_abbrev);
687 defsubr (&Sdefine_global_abbrev);
688 defsubr (&Sdefine_mode_abbrev);
689 defsubr (&Sabbrev_expansion);
690 defsubr (&Sabbrev_symbol);
691 defsubr (&Sexpand_abbrev);
692 defsubr (&Sunexpand_abbrev);
693 defsubr (&Sinsert_abbrev_table_description);
694 defsubr (&Sdefine_abbrev_table);
695}
ab5796a9
MB
696
697/* arch-tag: b721db69-f633-44a8-a361-c275acbdad7d
698 (do not change this comment) */