(eval-after-load): Allow form to be a function.
take advantage of lexical-binding.
(do-after-load-evaluation): Use dolist and adjust to new format.
* lisp/simple.el (bad-packages-alist): Use dolist and with-eval-after-load.
* doc/lispref/loading.texi (Hooks for Loading): Document with-eval-after-load
instead of eval-after-load. Don't document after-load-alist.
* src/lread.c (syms_of_lread):
* src/fns.c (Fprovide): Adjust to new format of after-load-alist.
+2013-06-13 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * loading.texi (Hooks for Loading): Don't document after-load-alist.
+ Document with-eval-after-load instead of eval-after-load.
+
2013-06-11 Xue Fuqiao <xfq.free@gmail.com>
* files.texi (File Name Expansion): Make the example more
@end defvar
If you want code to be executed when a @emph{particular} library is
-loaded, use the function @code{eval-after-load}:
+loaded, use the macro @code{with-eval-after-load}:
-@defun eval-after-load library form
-This function arranges to evaluate @var{form} at the end of loading
+@defmac with-eval-after-load library body@dots{}
+This macro arranges to evaluate @var{body} at the end of loading
the file @var{library}, each time @var{library} is loaded. If
-@var{library} is already loaded, it evaluates @var{form} right away.
-Don't forget to quote @var{form}!
+@var{library} is already loaded, it evaluates @var{body} right away.
You don't need to give a directory or extension in the file name
@var{library}. Normally, you just give a bare file name, like this:
@example
-(eval-after-load "edebug" '(def-edebug-spec c-point t))
+(with-eval-after-load "edebug" (def-edebug-spec c-point t))
@end example
To restrict which files can trigger the evaluation, include a
@file{my_inst.el}:
@example
-(eval-after-load "foo/bar/my_inst.elc" @dots{})
+(with-eval-after-load "foo/bar/my_inst.elc" @dots{})
@end example
@var{library} can also be a feature (i.e., a symbol), in which case
-@var{form} is evaluated at the end of any file where
+@var{body} is evaluated at the end of any file where
@code{(provide @var{library})} is called.
-An error in @var{form} does not undo the load, but does prevent
-execution of the rest of @var{form}.
-@end defun
+An error in @var{body} does not undo the load, but does prevent
+execution of the rest of @var{body}.
+@end defmac
Normally, well-designed Lisp programs should not use
@code{eval-after-load}. If you need to examine and set the variables
it immediately---there is no need to wait until the library is loaded.
If you need to call functions defined by that library, you should load
the library, preferably with @code{require} (@pxref{Named Features}).
-
-@defvar after-load-alist
-This variable stores an alist built by @code{eval-after-load},
-containing the expressions to evaluate when certain libraries are
-loaded. Each element looks like this:
-
-@example
-(@var{regexp-or-feature} @var{forms}@dots{})
-@end example
-
-The key @var{regexp-or-feature} is either a regular expression or a
-symbol, and the value is a list of forms. The forms are evaluated
-when the key matches the absolute true name or feature name of the
-library being loaded.
-@end defvar
\f
* Lisp Changes in Emacs 24.4
-FIXME - someone who knows what they are talking about, please improve
-this - see http://debbugs.gnu.org/14596
++++
+** New macro with-eval-after-load. Like eval-after-load, but better behaved.
+
** The default file coding for Emacs Lisp files is now utf-8.
(See file-coding-system-alist.) In most cases, this change is
totally transparent. Files that contain unusual characters but do
+2013-06-13 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * subr.el (with-eval-after-load): New macro.
+ (eval-after-load): Allow form to be a function.
+ take advantage of lexical-binding.
+ (do-after-load-evaluation): Use dolist and adjust to new format.
+ * simple.el (bad-packages-alist): Use dolist and with-eval-after-load.
+
2013-06-13 Juri Linkov <juri@jurta.org>
* replace.el (perform-replace): Display "symbol " and other search
"Alist of packages known to cause problems in this version of Emacs.
Each element has the form (PACKAGE SYMBOL REGEXP STRING).
PACKAGE is either a regular expression to match file names, or a
-symbol (a feature name); see the documentation of
-`after-load-alist', to which this variable adds functions.
+symbol (a feature name), like for `with-eval-after-load'.
SYMBOL is either the name of a string variable, or `t'. Upon
loading PACKAGE, if SYMBOL is t or matches REGEXP, display a
warning using STRING as the message.")
(display-warning package (nth 3 list) :warning)))
(error nil)))
-(mapc (lambda (elem)
- (eval-after-load (car elem) `(bad-package-check ',(car elem))))
- bad-packages-alist)
-
+(dolist (elem bad-packages-alist)
+ (let ((pkg (car elem)))
+ (with-eval-after-load pkg
+ (bad-package-check pkg))))
(provide 'simple)
(defun eval-after-load (file form)
"Arrange that if FILE is loaded, FORM will be run immediately afterwards.
If FILE is already loaded, evaluate FORM right now.
+FORM can be an Elisp expression (in which case it's passed to `eval'),
+or a function (in which case it's passed to `funcall' with no argument).
If a matching file is loaded again, FORM will be evaluated again.
like 'font-lock.
This function makes or adds to an entry on `after-load-alist'."
+ (declare (compiler-macro
+ (lambda (whole)
+ (if (eq 'quote (car-safe form))
+ ;; Quote with lambda so the compiler can look inside.
+ `(eval-after-load ,file (lambda () ,(nth 1 form)))
+ whole))))
;; Add this FORM into after-load-alist (regardless of whether we'll be
;; evaluating it now).
(let* ((regexp-or-feature
(if (stringp file)
(setq file (purecopy (load-history-regexp file)))
file))
- (elt (assoc regexp-or-feature after-load-alist)))
+ (elt (assoc regexp-or-feature after-load-alist))
+ (func
+ (if (functionp form) form
+ ;; Try to use the "current" lexical/dynamic mode for `form'.
+ (eval `(lambda () ,form) lexical-binding))))
(unless elt
(setq elt (list regexp-or-feature))
(push elt after-load-alist))
- ;; Make sure `form' is evalled in the current lexical/dynamic code.
- (setq form `(funcall ',(eval `(lambda () ,form) lexical-binding)))
;; Is there an already loaded file whose name (or `provide' name)
;; matches FILE?
(prog1 (if (if (stringp file)
(load-history-filename-element regexp-or-feature)
(featurep file))
- (eval form))
- (when (symbolp regexp-or-feature)
- ;; For features, the after-load-alist elements get run when `provide' is
- ;; called rather than at the end of the file. So add an indirection to
- ;; make sure that `form' is really run "after-load" in case the provide
- ;; call happens early.
- (setq form
- `(if load-file-name
- (let ((fun (make-symbol "eval-after-load-helper")))
- (fset fun `(lambda (file)
- (if (not (equal file ',load-file-name))
- nil
- (remove-hook 'after-load-functions ',fun)
- ,',form)))
- (add-hook 'after-load-functions fun))
- ;; Not being provided from a file, run form right now.
- ,form)))
- ;; Add FORM to the element unless it's already there.
- (unless (member form (cdr elt))
- (nconc elt (list form))))))
+ (funcall func))
+ (let ((delayed-func
+ (if (not (symbolp regexp-or-feature)) func
+ ;; For features, the after-load-alist elements get run when
+ ;; `provide' is called rather than at the end of the file.
+ ;; So add an indirection to make sure that `func' is really run
+ ;; "after-load" in case the provide call happens early.
+ (lambda ()
+ (if (not load-file-name)
+ ;; Not being provided from a file, run func right now.
+ (funcall func)
+ (let ((lfn load-file-name))
+ (letrec ((fun (lambda (file)
+ (when (equal file lfn)
+ (remove-hook 'after-load-functions fun)
+ (funcall func)))))
+ (add-hook 'after-load-functions fun))))))))
+ ;; Add FORM to the element unless it's already there.
+ (unless (member delayed-func (cdr elt))
+ (nconc elt (list delayed-func)))))))
+
+(defmacro with-eval-after-load (file &rest body)
+ "Execute BODY after FILE is loaded.
+FILE is normally a feature name, but it can also be a file name,
+in case that file does not provide any feature."
+ (declare (indent 1) (debug t))
+ `(eval-after-load ,file (lambda () ,@body)))
(defvar after-load-functions nil
"Special hook run after loading a file.
ABS-FILE, a string, should be the absolute true name of a file just loaded.
This function is called directly from the C code."
;; Run the relevant eval-after-load forms.
- (mapc #'(lambda (a-l-element)
- (when (and (stringp (car a-l-element))
- (string-match-p (car a-l-element) abs-file))
- ;; discard the file name regexp
- (mapc #'eval (cdr a-l-element))))
- after-load-alist)
+ (dolist (a-l-element after-load-alist)
+ (when (and (stringp (car a-l-element))
+ (string-match-p (car a-l-element) abs-file))
+ ;; discard the file name regexp
+ (mapc #'funcall (cdr a-l-element))))
;; Complain when the user uses obsolete files.
(when (string-match-p "/obsolete/[^/]*\\'" abs-file)
(run-with-timer 0 nil
+2013-06-13 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lread.c (syms_of_lread):
+ * fns.c (Fprovide): Adjust to new format of after-load-alist.
+
2013-06-13 Kelly Dean <kellydeanch@yahoo.com> (tiny change)
* fileio.c (Fdo_auto_save): Trap errors in auto-save-hook. (Bug#14479)
return (NILP (tem)) ? Qnil : Qt;
}
+static Lisp_Object Qfuncall;
+
DEFUN ("provide", Fprovide, Sprovide, 1, 2, 0,
doc: /* Announce that FEATURE is a feature of the current Emacs.
The optional argument SUBFEATURES should be a list of symbols listing
/* Run any load-hooks for this file. */
tem = Fassq (feature, Vafter_load_alist);
if (CONSP (tem))
- Fprogn (XCDR (tem));
+ Fmapc (Qfuncall, XCDR (tem));
return feature;
}
Used by `featurep' and `require', and altered by `provide'. */);
Vfeatures = Fcons (intern_c_string ("emacs"), Qnil);
DEFSYM (Qsubfeatures, "subfeatures");
+ DEFSYM (Qfuncall, "funcall");
#ifdef HAVE_LANGINFO_CODESET
DEFSYM (Qcodeset, "codeset");
DEFSYM (Qload_in_progress, "load-in-progress");
DEFVAR_LISP ("after-load-alist", Vafter_load_alist,
- doc: /* An alist of expressions to be evalled when particular files are loaded.
-Each element looks like (REGEXP-OR-FEATURE FORMS...).
+ doc: /* An alist of functions to be evalled when particular files are loaded.
+Each element looks like (REGEXP-OR-FEATURE FUNCS...).
REGEXP-OR-FEATURE is either a regular expression to match file names, or
a symbol \(a feature name).
When `load' is run and the file-name argument matches an element's
REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol
-REGEXP-OR-FEATURE, the FORMS in the element are executed.
+REGEXP-OR-FEATURE, the FUNCS in the element are called.
An error in FORMS does not undo the load, but does prevent execution of
the rest of the FORMS. */);