Add a comment for the previous commit.
[bpt/emacs.git] / lisp / abbrev.el
index 303f035..b72bdbb 100644 (file)
@@ -1,17 +1,17 @@
 ;;; abbrev.el --- abbrev mode commands for Emacs
 
 ;; Copyright (C) 1985, 1986, 1987, 1992, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;;   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: abbrev convenience
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; 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 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,9 +19,7 @@
 ;; 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., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -29,7 +27,6 @@
 
 ;; Todo:
 
-;; - Make abbrev-file-name obey user-emacs-directory.
 ;; - Cleanup name space.
 
 ;;; Code:
   :link '(custom-manual "(emacs)Abbrevs")
   :group 'abbrev)
 
+(defcustom abbrev-file-name
+  (locate-user-emacs-file "abbrev_defs" ".abbrev_defs")
+  "Default name of file from which to read abbrevs."
+  :initialize 'custom-initialize-delay
+  :type 'file)
+
 (defcustom only-global-abbrevs nil
   "Non-nil means user plans to use global abbrevs only.
 This makes the commands that normally define mode-specific abbrevs
@@ -389,43 +392,6 @@ See `define-abbrev' for the effect of some special properties.
 
 \(fn ABBREV PROP VAL)")
 
-(defmacro abbrev-with-wrapper-hook (var &rest body)
-  "Run BODY wrapped with the VAR hook.
-VAR is a special hook: its functions are called with one argument which
-is the \"original\" code (the BODY), so the hook function can wrap the
-original function, can call it several times, or even not call it at all.
-VAR is normally a symbol (a variable) in which case it is treated like a hook,
-with a buffer-local and a global part.  But it can also be an arbitrary expression.
-This is similar to an `around' advice."
-  (declare (indent 1) (debug t))
-  ;; We need those two gensyms because CL's lexical scoping is not available
-  ;; for function arguments :-(
-  (let ((funs (make-symbol "funs"))
-        (global (make-symbol "global")))
-    ;; Since the hook is a wrapper, the loop has to be done via
-    ;; recursion: a given hook function will call its parameter in order to
-    ;; continue looping.
-    `(labels ((runrestofhook (,funs ,global)
-                 ;; `funs' holds the functions left on the hook and `global'
-                 ;; holds the functions left on the global part of the hook
-                 ;; (in case the hook is local).
-                 (lexical-let ((funs ,funs)
-                               (global ,global))
-                   (if (consp funs)
-                       (if (eq t (car funs))
-                           (runrestofhook (append global (cdr funs)) nil)
-                         (funcall (car funs)
-                                  (lambda () (runrestofhook (cdr funs) global))))
-                     ;; Once there are no more functions on the hook, run
-                     ;; the original body.
-                     ,@body))))
-       (runrestofhook ,var
-                      ;; The global part of the hook, if any.
-                      ,(if (symbolp var)
-                           `(if (local-variable-p ',var)
-                                (default-value ',var)))))))
-
-
 ;;; Code that used to be implemented in src/abbrev.c
 
 (defvar abbrev-table-name-list '(fundamental-mode-abbrev-table
@@ -523,7 +489,9 @@ the current abbrev table before abbrev lookup happens."
       (set newsym nil)      ; Make sure it won't be confused for an abbrev.
       (setplist newsym (symbol-plist sym)))
     (abbrev-table-put table :abbrev-table-modiff
-                      (1+ (abbrev-table-get table :abbrev-table-modiff)))))
+                      (1+ (abbrev-table-get table :abbrev-table-modiff))))
+  ;; For backward compatibility, always return nil.
+  nil)
 
 (defun define-abbrev (table name expansion &optional hook &rest props)
   "Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.
@@ -532,8 +500,9 @@ 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.
+If EXPANSION is not a string (and not nil), the abbrev is a
+ special one, which does not expand in the usual way but only
+ runs HOOK.
 
 PROPS is a property list.  The following properties are special:
 - `:count': the value for the abbrev's usage-count, which is incremented each
@@ -544,7 +513,7 @@ PROPS is a property list.  The following properties are special:
   overwrite a non-system abbreviation of the same name.
 - `:case-fixed': non-nil means that abbreviations are looked up without
   case-folding, and the expansion is not capitalized/upcased.
-- `:enable-function': a function of no argument which returns non-nil iff the
+- `:enable-function': a function of no argument which returns non-nil if the
   abbrev should be used for a particular call of `expand-abbrev'.
 
 An obsolete but still supported calling form is:
@@ -702,11 +671,19 @@ then ABBREV is looked up in that table only."
           (setq tables (append (abbrev-table-get table :parents) tables))
           (setq res
                 (and (or (not enable-fun) (funcall enable-fun))
-                     (looking-back (or (abbrev-table-get table :regexp)
-                                       "\\<\\(\\w+\\)\\W*")
-                                   (line-beginning-position))
-                     (setq start (match-beginning 1))
-                     (setq end   (match-end 1))
+                     (let ((re (abbrev-table-get table :regexp)))
+                       (if (null re)
+                           ;; We used to default `re' to "\\<\\(\\w+\\)\\W*"
+                           ;; but when words-include-escapes is set, that
+                           ;; is not right and fixing it is boring.
+                           (let ((lim (point)))
+                             (backward-word 1)
+                             (setq start (point))
+                             (forward-word 1)
+                             (setq end (min (point) lim)))
+                         (when (looking-back re (line-beginning-position))
+                           (setq start (match-beginning 1))
+                           (setq end   (match-end 1)))))
                      (setq name  (buffer-substring start end))
                      (let ((abbrev (abbrev-symbol name table)))
                        (when abbrev
@@ -723,7 +700,7 @@ then ABBREV is looked up in that table only."
   "Insert abbrev ABBREV at point.
 If non-nil, NAME is the name by which this abbrev was found.
 If non-nil, WORDSTART is the place where to insert the abbrev.
-If non-nil, WORDEND the abbrev replaces the previous text between
+If WORDEND is non-nil, the abbrev replaces the previous text between
 WORDSTART and WORDEND.
 Return ABBREV if the expansion should be considered as having taken place."
   (unless name (setq name (symbol-name abbrev)))
@@ -793,7 +770,7 @@ Effective when explicitly called even when `abbrev-mode' is nil.
 Returns the abbrev symbol, if expansion took place."
   (interactive)
   (run-hooks 'pre-abbrev-expand-hook)
-  (abbrev-with-wrapper-hook abbrev-expand-functions
+  (with-wrapper-hook abbrev-expand-functions ()
     (destructuring-bind (&optional sym name wordstart wordend)
         (abbrev--before-point)
       (when sym
@@ -826,10 +803,11 @@ is not undone."
         ;; to do the expansion.
         (let ((val (symbol-value last-abbrev)))
           (unless (stringp val)
-            (error "value of abbrev-symbol must be a string"))
-          (delete-region (point) (+ (point) (length val)))
+            (error "Value of abbrev-symbol must be a string"))
           ;; Don't inherit properties here; just copy from old contents.
           (insert last-abbrev-text)
+          ;; Delete after inserting, to better preserve markers.
+          (delete-region (point) (+ (point) (length val)))
           (setq last-abbrev-text nil))))))
 
 (defun abbrev--write (sym)
@@ -885,9 +863,11 @@ Abbrevs marked as \"system abbrevs\" are omitted."
            (insert "\n\n"))
        (insert "(define-abbrev-table '")
        (prin1 name)
-       (insert " '(")
-       (mapc 'abbrev--write symbols)
-       (insert "    ))\n\n"))
+       (if (null symbols)
+           (insert " '())\n\n")
+         (insert "\n  '(\n")
+         (mapc 'abbrev--write symbols)
+         (insert "   ))\n\n")))
       nil)))
 
 (put 'define-abbrev-table 'doc-string-elt 3)
@@ -906,17 +886,22 @@ Properties with special meaning:
   means that an abbrev can only be a single word.  The submatch 1 is treated
   as the potential name of an abbrev.
 - `:enable-function' can be set to a function of no argument which returns
-  non-nil iff the abbrevs in this table should be used for this instance
-  of `expand-abbrev'."
+  non-nil if and only if the abbrevs in this table should be used for this
+  instance of `expand-abbrev'."
   ;; We used to manually add the docstring, but we also want to record this
   ;; location as the definition of the variable (in load-history), so we may
   ;; as well just use `defvar'.
   (eval `(defvar ,tablename nil ,@(if (stringp docstring) (list docstring))))
   (let ((table (if (boundp tablename) (symbol-value tablename))))
     (unless table
-      (setq table (make-abbrev-table props))
+      (setq table (make-abbrev-table))
       (set tablename table)
       (push tablename abbrev-table-name-list))
+    ;; We used to just pass them to `make-abbrev-table', but that fails
+    ;; if the table was pre-existing as is the case if it was created by
+    ;; loading the user's abbrev file.
+    (while (consp props)
+      (abbrev-table-put table (pop props) (pop props)))
     (dolist (elt definitions)
       (apply 'define-abbrev table elt))))