1: /* Word-abbrev mode.  Copyright (C) 1985 Richard M. Stallman.
   2: 
   3: This file is part of GNU Emacs.
   4: 
   5: GNU Emacs is distributed in the hope that it will be useful,
   6: but WITHOUT ANY WARRANTY.  No author or distributor
   7: accepts responsibility to anyone for the consequences of using it
   8: or for whether it serves any particular purpose or works at all,
   9: unless he says so in writing.  Refer to the GNU Emacs General Public
  10: License for full details.
  11: 
  12: Everyone is granted permission to copy, modify and redistribute
  13: GNU Emacs, but only under the conditions described in the
  14: GNU Emacs General Public License.   A copy of this license is
  15: supposed to have been given to you along with GNU Emacs so you
  16: can know your rights and responsibilities.  It should be in a
  17: file named COPYING.  Among other things, the copyright notice
  18: and this notice must be preserved on all copies.  */
  19: 
  20: 
  21: #include "config.h"
  22: #include <stdio.h>
  23: #undef NULL
  24: #include "lisp.h"
  25: #include "commands.h"
  26: #include "buffer.h"
  27: 
  28: /* An abbrev table is an obarray.
  29:  Each defined abbrev is represented by a symbol in that obarray
  30:  whose print name is the abbreviation.
  31:  The symbol's value is a string which is the expansion.
  32:  If its function definition is non-nil, it is called
  33:   after the expansion is done.
  34:  The plist slot of the abbrev symbol is its usage count. */
  35: 
  36: /* List of all abbrev-table name symbols:
  37:  symbols whose values are abbrev tables.  */
  38: 
  39: Lisp_Object Vabbrev_table_name_list;
  40: 
  41: /* The table of global abbrevs.  These are in effect
  42:  in any buffer in which abbrev mode is turned on. */
  43: 
  44: Lisp_Object Vglobal_abbrev_table;
  45: 
  46: /* The local abbrev table used by default (in Fundamental Mode buffers) */
  47: 
  48: Lisp_Object Vfundamental_mode_abbrev_table;
  49: 
  50: /* Set nonzero when an abbrev definition is changed */
  51: 
  52: int abbrevs_changed;
  53: 
  54: int abbrev_all_caps;
  55: 
  56: /* Non-nil => use this location as the start of abbrev to expand
  57:  (rather than taking the word before point as the abbrev) */
  58: 
  59: Lisp_Object Vabbrev_start_location;
  60: 
  61: /* Buffer that Vabbrev_start_location applies to */
  62: Lisp_Object Vabbrev_start_location_buffer;
  63: 
  64: /* The symbol representing the abbrev most recently expanded */
  65: 
  66: Lisp_Object Vlast_abbrev;
  67: 
  68: /* Character address of start of last abbrev expanded */
  69: 
  70: int last_abbrev_point;
  71: 
  72: extern Lisp_Object oblookup ();
  73: 
  74: DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
  75:   "Create a new, empty abbrev table object.")
  76:   ()
  77: {
  78:   return Fmake_vector (make_number (59), make_number (0));
  79: }
  80: 
  81: DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
  82:   "Undefine all abbrevs in abbrev table TABLE, leaving it empty.")
  83:   (table)
  84:      Lisp_Object table;
  85: {
  86:   int i, size;
  87: 
  88:   CHECK_VECTOR (table, 0);
  89:   size = XVECTOR (table)->size;
  90:   abbrevs_changed = 1;
  91:   for (i = 0; i < size; i++)
  92:     XVECTOR (table)->contents[i] = make_number (0);
  93:   return Qnil;
  94: }
  95: 
  96: DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 5, 0,
  97:   "Define an abbrev in TABLE named NAME, to expand to EXPANSION or call HOOK.\n\
  98: NAME and EXPANSION are strings.  HOOK is a function or nil.\n\
  99: To undefine an abbrev, define it with EXPANSION = nil")
 100:   (table, name, expansion, hook, count)
 101:      Lisp_Object table, name, expansion, hook, count;
 102: {
 103:   Lisp_Object sym, oexp, ohook, tem;
 104:   CHECK_VECTOR (table, 0);
 105:   CHECK_STRING (name, 1);
 106:   CHECK_STRING (expansion, 2);
 107:   if (NULL (count))
 108:     count = make_number (0);
 109:   else
 110:     CHECK_NUMBER (count, 0);
 111: 
 112:   sym = Fintern (name, table);
 113: 
 114:   oexp = XSYMBOL (sym)->value;
 115:   ohook = XSYMBOL (sym)->function;
 116:   if (!((EQ (oexp, expansion)
 117:      || (XTYPE (oexp) == Lisp_String
 118:          && (tem = Fstring_equal (oexp, expansion), !NULL (tem))))
 119:     &&
 120:     (EQ (ohook, hook)
 121:      || (tem = Fequal (ohook, hook), !NULL (tem)))))
 122:     abbrevs_changed = 1;
 123: 
 124:   Fset (sym, expansion);
 125:   Ffset (sym, hook);
 126:   Fsetplist (sym, count);
 127: 
 128:   return name;
 129: }
 130: 
 131: DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
 132:   "sDefine global abbrev: \nsExpansion for %s: ",
 133:   "Define ABBREV as a global abbreviation for EXPANSION.")
 134:   (name, expansion)
 135:      Lisp_Object name, expansion;
 136: {
 137:   Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (name),
 138:           expansion, Qnil, make_number (0));
 139:   return name;
 140: }
 141: 
 142: DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
 143:   "sDefine mode abbrev: \nsExpansion for %s: ",
 144:   "Define ABBREV as a mode-specific abbreviation for EXPANSION.")
 145:   (name, expansion)
 146:      Lisp_Object name, expansion;
 147: {
 148:   if (NULL (bf_cur->abbrev_table))
 149:     error ("No local abbrev table associated with this buffer");
 150: 
 151:   Fdefine_abbrev (bf_cur->abbrev_table, Fdowncase (name),
 152:           expansion, Qnil, make_number (0));
 153:   return name;
 154: }
 155: 
 156: DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
 157:   "Return the symbol representing abbrev named ABBREV.\n\
 158: Value is nil if that abbrev is not defined.\n\
 159: Optional second arg TABLE is abbrev table to look it up in.\n\
 160: Default is try buffer's mode-specific abbrev table, then global table.")
 161:   (abbrev, table)
 162:      Lisp_Object abbrev, table;
 163: {
 164:   Lisp_Object sym;
 165:   CHECK_STRING (abbrev, 0);
 166:   if (!NULL (table))
 167:     sym = Fintern_soft (abbrev, table);
 168:   else
 169:     {
 170:       sym = Qnil;
 171:       if (!NULL (bf_cur->abbrev_table))
 172:     sym = Fintern_soft (abbrev, bf_cur->abbrev_table);
 173:       if (NULL (XSYMBOL (sym)->value))
 174:     sym = Qnil;
 175:       if (NULL (sym))
 176:     sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
 177:     }
 178:   if (NULL (XSYMBOL (sym)->value)) return Qnil;
 179:   return sym;
 180: }
 181: 
 182: DEFUN ("abbrev-expansion", Fabbrev_expansion, Sabbrev_expansion, 1, 2, 0,
 183:   "Return the string that ABBREV expands into in the current buffer.\n\
 184: Optionally specify an abbrev table; then ABBREV is looked up in that table only.")
 185:   (abbrev, table)
 186:      Lisp_Object abbrev, table;
 187: {
 188:   Lisp_Object sym;
 189:   sym = Fabbrev_symbol (abbrev, table);
 190:   if (NULL (sym)) return sym;
 191:   return Fsymbol_value (sym);
 192: }
 193: 
 194: /* Expand the word before point, if it is an abbrev.
 195:   Returns 1 if an expansion is done. */
 196: 
 197: DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
 198:   "Expand the abbrev before point, if it is an abbrev.\n\
 199: Returns t if expansion took place.")
 200:   ()
 201: {
 202:   char buffer[200];
 203:   char *p = buffer;
 204:   int wordstart, idx;
 205:   int uccount = 0, lccount = 0;
 206:   Lisp_Object sym, expansion, hook, tem;
 207: 
 208:   if (XBUFFER (Vabbrev_start_location_buffer) != bf_cur)
 209:     Vabbrev_start_location = Qnil;
 210:   if (!NULL (Vabbrev_start_location))
 211:     {
 212:       tem = Vabbrev_start_location;
 213:       CHECK_NUMBER_COERCE_MARKER (tem, 0);
 214:       wordstart = XINT (tem);
 215:       Vabbrev_start_location = Qnil;
 216:     }
 217:   else
 218:     wordstart = scan_words (point, -1);
 219: 
 220:   if (!wordstart || point - wordstart >= sizeof buffer || point <= wordstart)
 221:     return Qnil;
 222: 
 223:   for (idx = wordstart; idx < point; idx++)
 224:     {
 225:       *p = CharAt (idx);
 226:       if (*p >= 'A' && *p <= 'Z')
 227:     *p += 040, uccount++;
 228:       else if (*p >= 'a' && *p <= 'z')
 229:     lccount++;
 230:       p++;
 231:     }
 232: 
 233:   if (XTYPE (bf_cur->abbrev_table) == Lisp_Vector)
 234:     sym = oblookup (bf_cur->abbrev_table, buffer, p - buffer);
 235:   else
 236:     XFASTINT (sym) = 0;
 237:   if (XTYPE (sym) == Lisp_Int ||
 238:       NULL (XSYMBOL (sym)->value))
 239:     sym = oblookup (Vglobal_abbrev_table, buffer, p - buffer);
 240:   if (XTYPE (sym) == Lisp_Int ||
 241:       NULL (XSYMBOL (sym)->value))
 242:     return Qnil;
 243: 
 244:   SetPoint (wordstart);
 245:   del_range (point, point + (p - buffer));
 246: 
 247:   /* Now sym is the abbrev symbol. */
 248:   Vlast_abbrev = sym;
 249:   last_abbrev_point = point;
 250: 
 251:   if (XTYPE (XSYMBOL (sym)->plist) == Lisp_Int)
 252:     XSETINT (XSYMBOL (sym)->plist,
 253:          XINT (XSYMBOL (sym)->plist) + 1);  /* Increment use count */
 254: 
 255:   hook = XSYMBOL (sym)->function;
 256:   if (!NULL (hook))
 257:     Fapply (hook, Qnil);
 258:   else
 259:     {
 260:       expansion = XSYMBOL (sym)->value;
 261:       InsCStr (XSTRING (expansion)->data, XSTRING (expansion)->size);
 262: 
 263:       if (uccount && !lccount)
 264:     {
 265:       /* Abbrev was all caps */
 266:       /* If expansion is multiple words, normally capitalize each word */
 267:       /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
 268: 	     but Megatest 68000 compiler can't handle that */
 269:       if (!abbrev_all_caps)
 270:         if (scan_words (point, -1) > scan_words (wordstart, 1))
 271:           {
 272:         upcase_initials_region (make_number (wordstart),
 273:                     make_number (point));
 274:         goto caped;
 275:           }
 276:       /* If expansion is one word, or if user says so, upcase it all. */
 277:       Fupcase_region (make_number (wordstart), make_number (point));
 278:     caped: ;
 279:     }
 280:       else if (uccount)
 281:     {
 282:       /* Abbrev included some caps.  Cap first initial of expansion */
 283:       idx = point;
 284:       SetPoint (wordstart);
 285:       Fcapitalize_word (make_number (1));
 286:       SetPoint (idx);
 287:     }
 288:     }
 289: 
 290:   return Qt;
 291: }
 292: 
 293: DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
 294:   "Undo the expansion of the last abbrev that expanded.")
 295:   ()
 296: {
 297:   SetPoint (last_abbrev_point);
 298:   if (NULL (Vlast_abbrev))
 299:     {
 300:       Fforward_word (make_number (1));
 301:       Fexpand_abbrev ();
 302:     }
 303:   else if (XTYPE (Vlast_abbrev) == Lisp_Symbol)
 304:     {
 305:       del_range (point, point + XSTRING (XSYMBOL (Vlast_abbrev)->value)->size);
 306:       InsCStr (XSYMBOL (Vlast_abbrev)->name->data, XSYMBOL (Vlast_abbrev)->name->size);
 307:       Vlast_abbrev = Qnil;
 308:     }
 309:   return Qnil;
 310: }
 311: 
 312: DEFUN ("last-abbrev-expansion", Flast_abbrev_expansion, Slast_abbrev_expansion, 0, 0, 0,
 313:   "Return expansion of last abbrev expanded, or nil.")
 314:   ()
 315: {
 316:   return Fsymbol_value (Vlast_abbrev);
 317: }
 318: 
 319: static
 320: write_abbrev (sym, stream)
 321:      Lisp_Object sym, stream;
 322: {
 323:   Lisp_Object name;
 324:   if (NULL (XSYMBOL (sym)->value))
 325:     return;
 326:   InsCStr ("    (", 5);
 327:   XSET (name, Lisp_String, XSYMBOL (sym)->name);
 328:   Fprin1 (name, stream);
 329:   InsCStr (" ", 1);
 330:   Fprin1 (XSYMBOL (sym)->value, stream);
 331:   InsCStr (" ", 1);
 332:   Fprin1 (XSYMBOL (sym)->function, stream);
 333:   InsCStr (" ", 1);
 334:   Fprin1 (XSYMBOL (sym)->plist, stream);
 335:   InsCStr (")\n", 2);
 336: }
 337: 
 338: static
 339: describe_abbrev (sym, stream)
 340:      Lisp_Object sym, stream;
 341: {
 342:   Lisp_Object one;
 343: 
 344:   if (NULL (XSYMBOL (sym)->value))
 345:     return;
 346:   one = make_number (1);
 347:   Fprin1 (Fsymbol_name (sym), stream);
 348:   Findent_to (make_number (15), one);
 349:   Fprin1 (XSYMBOL (sym)->plist, stream);
 350:   Findent_to (make_number (20), one);
 351:   Fprin1 (XSYMBOL (sym)->value, stream);
 352:   if (!NULL (XSYMBOL (sym)->function))
 353:     {
 354:       Findent_to (make_number (45), one);
 355:       Fprin1 (XSYMBOL (sym)->function, stream);
 356:     }
 357:   Fterpri (stream);
 358: }
 359: 
 360: DEFUN ("insert-abbrev-table-description",
 361:   Finsert_abbrev_table_description, Sinsert_abbrev_table_description,
 362:   2, 2, 0,
 363:   "Insert before point a description of abbrev table named NAME.\n\
 364: NAME is a symbol whose value is an abbrev table.\n\
 365: If 2nd arg READABLE is non-nil, a readable description is inserted.\n\
 366: Otherwise description is an expression,\n\
 367: a call to define-abbrev-table which would\n\
 368: define NAME exactly as it is currently defined.")
 369:   (name, readable)
 370:      Lisp_Object name, readable;
 371: {
 372:   Lisp_Object table;
 373:   Lisp_Object stream;
 374: 
 375:   CHECK_SYMBOL (name, 0);
 376:   table = Fsymbol_value (name);
 377:   CHECK_VECTOR (table, 0);
 378: 
 379:   XSET (stream, Lisp_Buffer, bf_cur);
 380: 
 381:   if (!NULL (readable))
 382:     {
 383:       InsStr ("(");
 384:       Fprin1 (name, stream);
 385:       InsStr (")\n\n");
 386:       map_obarray (table, describe_abbrev, stream);
 387:       InsStr ("\n\n");
 388:     }
 389:   else
 390:     {
 391:       InsStr ("(define-abbrev-table '");
 392:       Fprin1 (name, stream);
 393:       InsStr (" '(\n");
 394:       map_obarray (table, write_abbrev, stream);
 395:       InsStr ("    ))\n\n");
 396:     }
 397: 
 398:   return Qnil;
 399: }
 400: 
 401: DEFUN ("define-abbrev-table",
 402:        Fdefine_abbrev_table, Sdefine_abbrev_table, 2, 2, 0,
 403:   "Define TABNAME (a symbol) as an abbrev table name.\n\
 404: Define abbrevs in it according to DEFINITIONS, a list of elements\n\
 405: of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
 406:   (tabname, defns)
 407:      Lisp_Object tabname, defns;
 408: {
 409:   Lisp_Object name, exp, hook, count;
 410:   Lisp_Object table, elt;
 411: 
 412:   CHECK_SYMBOL (tabname, 0);
 413:   table = Fboundp (tabname);
 414:   if (NULL (table) || (table = Fsymbol_value (tabname), NULL (table)))
 415:     {
 416:       table = Fmake_abbrev_table ();
 417:       Fset (tabname, table);
 418:       Vabbrev_table_name_list =
 419:     Fcons (tabname, Vabbrev_table_name_list);
 420:     }
 421:   CHECK_VECTOR (table, 0);
 422: 
 423:   for (;!NULL (defns); defns = Fcdr (defns))
 424:     {
 425:       elt = Fcar (defns);
 426:       name = Fcar (elt);
 427:       elt = Fcdr (elt);
 428:       exp = Fcar (elt);
 429:       elt = Fcdr (elt);
 430:       hook = Fcar (elt);
 431:       elt = Fcdr (elt);
 432:       count = Fcar (elt);
 433:       Fdefine_abbrev (table, name, exp, hook, count);
 434:     }
 435:   return Qnil;
 436: }
 437: 
 438: syms_of_abbrev ()
 439: {
 440:   DefLispVar ("abbrev-table-name-list", &Vabbrev_table_name_list,
 441:     "List of symbols whose values are  abbrev tables.");
 442:   Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
 443:                    Fcons (intern ("global-abbrev-table"),
 444:                       Qnil));
 445: 
 446:   DefLispVar ("global-abbrev-table", &Vglobal_abbrev_table,
 447:     "The abbrev table whose abbrevs affect all buffers.\n\
 448: Each buffer may also have a local abbrev table.\n\
 449: If it does, the local table overrides the global one\n\
 450: for any particular abbrev defined in both.");
 451:   Vglobal_abbrev_table = Fmake_abbrev_table ();
 452: 
 453:   DefLispVar ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
 454:     "The abbrev table of mode-specific abbrevs for Fundamental Mode.");
 455:   Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
 456:   bf_cur->abbrev_table = Vfundamental_mode_abbrev_table;
 457: 
 458: /* Avoid need for some error checking this way
 459:   DefLispVar ("last-abbrev", &Vlast_abbrev,
 460:     "The abbrev-symbol of the last abbrev expanded.");
 461: 
 462:   DefIntVar ("last-abbrev-location", &last_abbrev_point,
 463:     "The location of the last abbrev expanded.");
 464: */
 465:   staticpro (&Vlast_abbrev);
 466:   Vlast_abbrev = Qnil;
 467:   last_abbrev_point = 0;
 468: 
 469:   DefLispVar ("abbrev-start-location", &Vabbrev_start_location,
 470:     "Buffer position for expand-abbrev to use as the start of the abbrev.\n\
 471: nil means use the word before point as the abbrev.\n\
 472: Set to nil each time expand-abbrev is called.");
 473:   Vabbrev_start_location = Qnil;
 474: 
 475:   DefLispVar ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
 476:     "Buffer that abbrev-start-location has been set for.\n\
 477: Trying to expand an abbrev in any other buffer clears abbrev-start-location.");
 478:   Vabbrev_start_location_buffer = Qnil;
 479: 
 480:   DefBufferLispVar ("local-abbrev-table", &bf_cur->abbrev_table,
 481:     "Local (mode-specific) abbrev table of current buffer.");
 482: 
 483:   DefBoolVar ("abbrevs-changed", &abbrevs_changed,
 484:     "Set non-nil by defining or altering any word abbrevs.");
 485:   abbrevs_changed = 0;
 486: 
 487:   DefBoolVar ("abbrev-all-caps", &abbrev_all_caps,
 488:     "*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
 489:   abbrev_all_caps = 0;
 490: 
 491:   defsubr (&Smake_abbrev_table);
 492:   defsubr (&Sclear_abbrev_table);
 493:   defsubr (&Sdefine_abbrev);
 494:   defsubr (&Sdefine_global_abbrev);
 495:   defsubr (&Sdefine_mode_abbrev);
 496:   defsubr (&Sabbrev_expansion);
 497:   defsubr (&Sabbrev_symbol);
 498:   defsubr (&Sexpand_abbrev);
 499:   defsubr (&Sunexpand_abbrev);
 500:   defsubr (&Slast_abbrev_expansion);
 501:   defsubr (&Sinsert_abbrev_table_description);
 502:   defsubr (&Sdefine_abbrev_table);
 503: }

Defined functions

DEFUN defined in line 401; never used
describe_abbrev defined in line 338; used 1 times
syms_of_abbrev defined in line 438; used 1 times
write_abbrev defined in line 319; used 1 times

Defined variables

Vabbrev_start_location defined in line 59; used 6 times
Vabbrev_start_location_buffer defined in line 62; used 3 times
Vabbrev_table_name_list defined in line 39; used 4 times
Vfundamental_mode_abbrev_table defined in line 48; used 3 times
Vglobal_abbrev_table defined in line 44; used 5 times
Vlast_abbrev defined in line 66; used 10 times
abbrev_all_caps defined in line 54; used 3 times
abbrevs_changed defined in line 52; used 4 times
last_abbrev_point defined in line 70; used 3 times
Last modified: 1986-01-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1703
Valid CSS Valid XHTML 1.0 Strict