X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/7ee72033eb52c5891e39c80b6db21e491ce0b187..cb94103f1744a17f140a94ba322a87e612d39d51:/src/abbrev.c diff --git a/src/abbrev.c b/src/abbrev.c index 723ec1ad42..bdb8dc66ba 100644 --- a/src/abbrev.c +++ b/src/abbrev.c @@ -1,12 +1,12 @@ /* Primitives for word-abbrev mode. - Copyright (C) 1985, 1986, 1993, 1996, 1998, 2001 - Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 1993, 1996, 1998, 2001, 2002, 2003, 2004, + 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, @@ -16,8 +16,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ #include @@ -77,16 +77,19 @@ Lisp_Object Vlast_abbrev_text; /* Character address of start of last abbrev expanded */ -int last_abbrev_point; +EMACS_INT last_abbrev_point; /* Hook to run before expanding any abbrev. */ Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook; + +Lisp_Object Qsystem_type, Qcount, Qforce; DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0, doc: /* Create a new, empty abbrev table object. */) () { + /* The value 59 is arbitrary chosen prime number. */ return Fmake_vector (make_number (59), make_number (0)); } @@ -97,36 +100,53 @@ DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0, { int i, size; - CHECK_VECTOR (table, 0); + CHECK_VECTOR (table); size = XVECTOR (table)->size; abbrevs_changed = 1; for (i = 0; i < size; i++) XVECTOR (table)->contents[i] = make_number (0); return Qnil; } - -DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 5, 0, + +DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 6, 0, doc: /* Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK. -NAME must be a string. +NAME must be a string, and should be lower-case. EXPANSION should usually be a string. To undefine an abbrev, define it with EXPANSION = nil. If HOOK is non-nil, it should be a function of no arguments; it is called after EXPANSION is inserted. If EXPANSION is not a string, the abbrev is a special one, which does not expand in the usual way but only runs HOOK. -COUNT, if specified, initializes the abbrev's usage-count -which is incremented each time the abbrev is used. */) - (table, name, expansion, hook, count) - Lisp_Object table, name, expansion, hook, count; + +COUNT, if specified, gives the initial value for the abbrev's +usage-count, which is incremented each time the abbrev is used. +\(The default is zero.) + +SYSTEM-FLAG, if non-nil, says that this is a "system" abbreviation +which should not be saved in the user's abbreviation file. +Unless SYSTEM-FLAG is `force', a system abbreviation will not +overwrite a non-system abbreviation of the same name. */) + (table, name, expansion, hook, count, system_flag) + Lisp_Object table, name, expansion, hook, count, system_flag; { Lisp_Object sym, oexp, ohook, tem; - CHECK_VECTOR (table, 0); - CHECK_STRING (name, 1); + CHECK_VECTOR (table); + CHECK_STRING (name); + + /* If defining a system abbrev, do not overwrite a non-system abbrev + of the same name, unless 'force is used. */ + if (!NILP (system_flag) && !EQ (system_flag, Qforce)) + { + sym = Fintern_soft (name, table); + + if (!NILP (SYMBOL_VALUE (sym)) && + NILP (Fplist_get (XSYMBOL (sym)->plist, Qsystem_type))) return Qnil; + } if (NILP (count)) count = make_number (0); else - CHECK_NUMBER (count, 0); + CHECK_NUMBER (count); sym = Fintern (name, table); @@ -137,12 +157,17 @@ which is incremented each time the abbrev is used. */) && (tem = Fstring_equal (oexp, expansion), !NILP (tem)))) && (EQ (ohook, hook) - || (tem = Fequal (ohook, hook), !NILP (tem))))) + || (tem = Fequal (ohook, hook), !NILP (tem)))) + && NILP (system_flag)) abbrevs_changed = 1; Fset (sym, expansion); Ffset (sym, hook); - Fsetplist (sym, count); + + if (! NILP (system_flag)) + Fsetplist (sym, list4 (Qcount, count, Qsystem_type, system_flag)); + else + Fsetplist (sym, count); return name; } @@ -154,7 +179,7 @@ DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, Lisp_Object abbrev, expansion; { Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (abbrev), - expansion, Qnil, make_number (0)); + expansion, Qnil, make_number (0), Qnil); return abbrev; } @@ -168,7 +193,7 @@ DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2, error ("Major mode has no abbrev table"); Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (abbrev), - expansion, Qnil, make_number (0)); + expansion, Qnil, make_number (0), Qnil); return abbrev; } @@ -183,7 +208,7 @@ The default is to try buffer's mode-specific abbrev table, then global table. * Lisp_Object abbrev, table; { Lisp_Object sym; - CHECK_STRING (abbrev, 0); + CHECK_STRING (abbrev); if (!NILP (table)) sym = Fintern_soft (abbrev, table); else @@ -225,17 +250,17 @@ Returns the abbrev symbol, if expansion took place. */) { register char *buffer, *p; int wordstart, wordend; - register int wordstart_byte, wordend_byte, idx; + register int wordstart_byte, wordend_byte, idx, idx_byte; int whitecnt; int uccount = 0, lccount = 0; register Lisp_Object sym; Lisp_Object expansion, hook, tem; Lisp_Object value; + int multibyte = ! NILP (current_buffer->enable_multibyte_characters); value = Qnil; - if (!NILP (Vrun_hooks)) - call1 (Vrun_hooks, Qpre_abbrev_expand_hook); + Frun_hooks (1, &Qpre_abbrev_expand_hook); wordstart = 0; if (!(BUFFERP (Vabbrev_start_location_buffer) @@ -244,7 +269,7 @@ Returns the abbrev symbol, if expansion took place. */) if (!NILP (Vabbrev_start_location)) { tem = Vabbrev_start_location; - CHECK_NUMBER_COERCE_MARKER (tem, 0); + CHECK_NUMBER_COERCE_MARKER (tem); wordstart = XINT (tem); Vabbrev_start_location = Qnil; if (wordstart < BEGV || wordstart > ZV) @@ -277,25 +302,39 @@ Returns the abbrev symbol, if expansion took place. */) p = buffer = (char *) alloca (wordend_byte - wordstart_byte); - for (idx = wordstart_byte; idx < wordend_byte; idx++) + for (idx = wordstart, idx_byte = wordstart_byte; idx < wordend; ) { - /* ??? This loop needs to go by characters! */ - register int c = FETCH_BYTE (idx); + register int c; + + if (multibyte) + { + FETCH_CHAR_ADVANCE (c, idx, idx_byte); + } + else + { + c = FETCH_BYTE (idx_byte); + idx++, idx_byte++; + } + if (UPPERCASEP (c)) c = DOWNCASE (c), uccount++; else if (! NOCASEP (c)) lccount++; - *p++ = c; + if (multibyte) + p += CHAR_STRING (c, p); + else + *p++ = c; } if (VECTORP (current_buffer->abbrev_table)) sym = oblookup (current_buffer->abbrev_table, buffer, - wordend - wordstart, wordend_byte - wordstart_byte); + wordend - wordstart, p - buffer); else XSETFASTINT (sym, 0); + if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym))) sym = oblookup (Vglobal_abbrev_table, buffer, - wordend - wordstart, wordend_byte - wordstart_byte); + wordend - wordstart, p - buffer); if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym))) return value; @@ -315,9 +354,12 @@ Returns the abbrev symbol, if expansion took place. */) value = sym; last_abbrev_point = wordstart; + /* Increment use count. */ if (INTEGERP (XSYMBOL (sym)->plist)) XSETINT (XSYMBOL (sym)->plist, - XINT (XSYMBOL (sym)->plist) + 1); /* Increment use count */ + XINT (XSYMBOL (sym)->plist) + 1); + else if (INTEGERP (tem = Fget (sym, Qcount))) + Fput (sym, Qcount, make_number (XINT (tem) + 1)); /* If this abbrev has an expansion, delete the abbrev and insert the expansion. */ @@ -326,10 +368,13 @@ Returns the abbrev symbol, if expansion took place. */) { SET_PT (wordstart); - del_range_both (wordstart, wordstart_byte, wordend, wordend_byte, 1); + insert_from_string (expansion, 0, 0, SCHARS (expansion), + SBYTES (expansion), 1); + del_range_both (PT, PT_BYTE, + wordend + (PT - wordstart), + wordend_byte + (PT_BYTE - wordstart_byte), + 1); - insert_from_string (expansion, 0, 0, XSTRING (expansion)->size, - STRING_BYTES (XSTRING (expansion)), 1); SET_PT (PT + whitecnt); if (uccount && !lccount) @@ -373,8 +418,8 @@ Returns the abbrev symbol, if expansion took place. */) /* If the abbrev has a hook function, run it. */ expanded = call0 (hook); - /* In addition, if the hook function is a symbol with a a - non-nil `no-self-insert' property, let the value it returned + /* In addition, if the hook function is a symbol with + a non-nil `no-self-insert' property, let the value it returned specify whether we consider that an expansion took place. If it returns nil, no expansion has been done. */ @@ -409,13 +454,13 @@ is not undone. */) val = SYMBOL_VALUE (Vlast_abbrev); if (!STRINGP (val)) - error ("value of abbrev-symbol must be a string"); + error ("Value of `abbrev-symbol' must be a string"); zv_before = ZV; - del_range_byte (PT_BYTE, PT_BYTE + STRING_BYTES (XSTRING (val)), 1); + del_range_byte (PT_BYTE, PT_BYTE + SBYTES (val), 1); /* Don't inherit properties here; just copy from old contents. */ insert_from_string (Vlast_abbrev_text, 0, 0, - XSTRING (Vlast_abbrev_text)->size, - STRING_BYTES (XSTRING (Vlast_abbrev_text)), 0); + SCHARS (Vlast_abbrev_text), + SBYTES (Vlast_abbrev_text), 0); Vlast_abbrev_text = Qnil; /* Total number of characters deleted. */ adjust = ZV - zv_before; @@ -428,18 +473,31 @@ static void write_abbrev (sym, stream) Lisp_Object sym, stream; { - Lisp_Object name; - if (NILP (SYMBOL_VALUE (sym))) + Lisp_Object name, count, system_flag; + + if (INTEGERP (XSYMBOL (sym)->plist)) + { + count = XSYMBOL (sym)->plist; + system_flag = Qnil; + } + else + { + count = Fget (sym, Qcount); + system_flag = Fget (sym, Qsystem_type); + } + + if (NILP (SYMBOL_VALUE (sym)) || ! NILP (system_flag)) return; + insert (" (", 5); - XSETSTRING (name, XSYMBOL (sym)->name); + name = SYMBOL_NAME (sym); Fprin1 (name, stream); insert (" ", 1); Fprin1 (SYMBOL_VALUE (sym), stream); insert (" ", 1); Fprin1 (XSYMBOL (sym)->function, stream); insert (" ", 1); - Fprin1 (XSYMBOL (sym)->plist, stream); + Fprin1 (count, stream); insert (")\n", 2); } @@ -447,14 +505,34 @@ static void describe_abbrev (sym, stream) Lisp_Object sym, stream; { - Lisp_Object one; + Lisp_Object one, count, system_flag; + + if (INTEGERP (XSYMBOL (sym)->plist)) + { + count = XSYMBOL (sym)->plist; + system_flag = Qnil; + } + else + { + count = Fget (sym, Qcount); + system_flag = Fget (sym, Qsystem_type); + } if (NILP (SYMBOL_VALUE (sym))) return; + one = make_number (1); Fprin1 (Fsymbol_name (sym), stream); - Findent_to (make_number (15), one); - Fprin1 (XSYMBOL (sym)->plist, stream); + + if (!NILP (system_flag)) + { + insert_string (" (sys)"); + Findent_to (make_number (20), one); + } + else + Findent_to (make_number (15), one); + + Fprin1 (count, stream); Findent_to (make_number (20), one); Fprin1 (SYMBOL_VALUE (sym), stream); if (!NILP (XSYMBOL (sym)->function)) @@ -465,32 +543,53 @@ describe_abbrev (sym, stream) Fterpri (stream); } +static void +record_symbol (sym, list) + Lisp_Object sym, list; +{ + XSETCDR (list, Fcons (sym, XCDR (list))); +} + DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description, - Sinsert_abbrev_table_description, 1, 2, 0, + Sinsert_abbrev_table_description, 1, 2, 0, doc: /* Insert before point a full description of abbrev table named NAME. NAME is a symbol whose value is an abbrev table. If optional 2nd arg READABLE is non-nil, a human-readable description is inserted. Otherwise the description is an expression, a call to `define-abbrev-table', which would -define the abbrev table NAME exactly as it is currently defined. */) +define the abbrev table NAME exactly as it is currently defined. + +Abbrevs marked as "system abbrevs" are normally omitted. However, if +READABLE is non-nil, they are listed. */) (name, readable) Lisp_Object name, readable; { Lisp_Object table; + Lisp_Object symbols; Lisp_Object stream; - CHECK_SYMBOL (name, 0); + CHECK_SYMBOL (name); table = Fsymbol_value (name); - CHECK_VECTOR (table, 0); + CHECK_VECTOR (table); XSETBUFFER (stream, current_buffer); + symbols = Fcons (Qnil, Qnil); + map_obarray (table, record_symbol, symbols); + symbols = XCDR (symbols); + symbols = Fsort (symbols, Qstring_lessp); + if (!NILP (readable)) { insert_string ("("); Fprin1 (name, stream); insert_string (")\n\n"); - map_obarray (table, describe_abbrev, stream); + while (! NILP (symbols)) + { + describe_abbrev (XCAR (symbols), stream); + symbols = XCDR (symbols); + } + insert_string ("\n\n"); } else @@ -498,7 +597,11 @@ define the abbrev table NAME exactly as it is currently defined. */) insert_string ("(define-abbrev-table '"); Fprin1 (name, stream); insert_string (" '(\n"); - map_obarray (table, write_abbrev, stream); + while (! NILP (symbols)) + { + write_abbrev (XCAR (symbols), stream); + symbols = XCDR (symbols); + } insert_string (" ))\n\n"); } @@ -509,14 +612,15 @@ DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table, 2, 2, 0, doc: /* Define TABLENAME (a symbol) as an abbrev table name. Define abbrevs in it according to DEFINITIONS, which is a list of elements -of the form (ABBREVNAME EXPANSION HOOK USECOUNT). */) +of the form (ABBREVNAME EXPANSION HOOK USECOUNT SYSTEMFLAG). +\(If the list is shorter than that, omitted elements default to nil). */) (tablename, definitions) Lisp_Object tablename, definitions; { Lisp_Object name, exp, hook, count; - Lisp_Object table, elt; + Lisp_Object table, elt, sys; - CHECK_SYMBOL (tablename, 0); + CHECK_SYMBOL (tablename); table = Fboundp (tablename); if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table))) { @@ -524,16 +628,17 @@ of the form (ABBREVNAME EXPANSION HOOK USECOUNT). */) Fset (tablename, table); Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list); } - CHECK_VECTOR (table, 0); + CHECK_VECTOR (table); - for (; !NILP (definitions); definitions = Fcdr (definitions)) + for (; CONSP (definitions); definitions = XCDR (definitions)) { - elt = Fcar (definitions); + elt = XCAR (definitions); name = Fcar (elt); elt = Fcdr (elt); exp = Fcar (elt); elt = Fcdr (elt); hook = Fcar (elt); elt = Fcdr (elt); - count = Fcar (elt); - Fdefine_abbrev (table, name, exp, hook, count); + count = Fcar (elt); elt = Fcdr (elt); + sys = Fcar (elt); + Fdefine_abbrev (table, name, exp, hook, count, sys); } return Qnil; } @@ -541,6 +646,15 @@ of the form (ABBREVNAME EXPANSION HOOK USECOUNT). */) void syms_of_abbrev () { + Qsystem_type = intern ("system-type"); + staticpro (&Qsystem_type); + + Qcount = intern ("count"); + staticpro (&Qcount); + + Qforce = intern ("force"); + staticpro (&Qforce); + DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list, doc: /* List of symbols whose values are abbrev tables. */); Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"), @@ -565,7 +679,7 @@ for any particular abbrev defined in both. */); DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text, doc: /* The exact text of the last abbrev expanded. -nil if the abbrev has already been unexpanded. */); +A value of nil means the abbrev has already been unexpanded. */); DEFVAR_INT ("last-abbrev-location", &last_abbrev_point, doc: /* The location of the start of the last abbrev expanded. */); @@ -576,7 +690,7 @@ nil if the abbrev has already been unexpanded. */); DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location, doc: /* Buffer position for `expand-abbrev' to use as the start of the abbrev. -nil means use the word before point as the abbrev. +When nil, use the word before point as the abbrev. Calling `expand-abbrev' sets this to nil. */); Vabbrev_start_location = Qnil; @@ -617,3 +731,6 @@ the current abbrev table before abbrev lookup happens. */); defsubr (&Sinsert_abbrev_table_description); defsubr (&Sdefine_abbrev_table); } + +/* arch-tag: b721db69-f633-44a8-a361-c275acbdad7d + (do not change this comment) */