Annotation of 43BSD/contrib/emacs/src/abbrev.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.