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