|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.