;;; 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
;; 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:
;; 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
\(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
(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.
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
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:
(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
"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)))
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
;; 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)
(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)
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))))