mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-27 07:37:33 +00:00
* lisp/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. * 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.
This commit is contained in:
parent
bc5c8c5a6a
commit
de0503df97
@ -1,3 +1,8 @@
|
||||
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
|
||||
|
@ -990,19 +990,18 @@ file that was just loaded.
|
||||
@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
|
||||
@ -1014,16 +1013,16 @@ example, @file{my_inst.elc} or @file{my_inst.elc.gz} in some directory
|
||||
@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
|
||||
@ -1031,18 +1030,3 @@ defined in another library (those meant for outside use), you can do
|
||||
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
|
||||
|
5
etc/NEWS
5
etc/NEWS
@ -452,8 +452,9 @@ file using `set-file-extended-attributes'.
|
||||
|
||||
* 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
|
||||
|
@ -1,3 +1,11 @@
|
||||
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
|
||||
|
@ -7295,8 +7295,7 @@ version and use the one distributed with Emacs."))
|
||||
"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.")
|
||||
@ -7314,10 +7313,10 @@ 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)
|
||||
|
||||
|
74
lisp/subr.el
74
lisp/subr.el
@ -3729,6 +3729,8 @@ Return nil if there isn't one."
|
||||
(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.
|
||||
|
||||
@ -3756,43 +3758,58 @@ Usually FILE is just a library name like \"font-lock\" or a feature name
|
||||
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.
|
||||
@ -3804,12 +3821,11 @@ name of the file just loaded.")
|
||||
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
|
||||
|
@ -1,3 +1,8 @@
|
||||
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)
|
||||
|
@ -2545,6 +2545,8 @@ SUBFEATURE can be used to check a specific subfeature of FEATURE. */)
|
||||
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
|
||||
@ -2567,7 +2569,7 @@ particular subfeatures supported in this version of FEATURE. */)
|
||||
/* 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;
|
||||
}
|
||||
@ -4866,6 +4868,7 @@ syms_of_fns (void)
|
||||
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");
|
||||
|
@ -4485,15 +4485,15 @@ customize `jka-compr-load-suffixes' rather than the present variable. */);
|
||||
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. */);
|
||||
|
Loading…
Reference in New Issue
Block a user