aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2013-06-13 18:24:52 -0400
committerStefan Monnier2013-06-13 18:24:52 -0400
commitde0503df97a507a523a192e877a8d5c7439c4846 (patch)
tree0753a678f85a7ea1a2eb46b81067e8a5d6dfc1e0
parentbc5c8c5a6a1956122284468879862b1850dc3b5d (diff)
downloademacs-de0503df97a507a523a192e877a8d5c7439c4846.tar.gz
emacs-de0503df97a507a523a192e877a8d5c7439c4846.zip
* 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.
-rw-r--r--doc/lispref/ChangeLog5
-rw-r--r--doc/lispref/loading.texi36
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/ChangeLog8
-rw-r--r--lisp/simple.el11
-rw-r--r--lisp/subr.el74
-rw-r--r--src/ChangeLog5
-rw-r--r--src/fns.c5
-rw-r--r--src/lread.c6
9 files changed, 88 insertions, 67 deletions
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index 259bf9a78a6..e14f7543443 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,8 @@
12013-06-13 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * loading.texi (Hooks for Loading): Don't document after-load-alist.
4 Document with-eval-after-load instead of eval-after-load.
5
12013-06-11 Xue Fuqiao <xfq.free@gmail.com> 62013-06-11 Xue Fuqiao <xfq.free@gmail.com>
2 7
3 * files.texi (File Name Expansion): Make the example more 8 * files.texi (File Name Expansion): Make the example more
diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi
index 5c92307f7d5..4c0f0d73e41 100644
--- a/doc/lispref/loading.texi
+++ b/doc/lispref/loading.texi
@@ -990,19 +990,18 @@ file that was just loaded.
990@end defvar 990@end defvar
991 991
992If you want code to be executed when a @emph{particular} library is 992If you want code to be executed when a @emph{particular} library is
993loaded, use the function @code{eval-after-load}: 993loaded, use the macro @code{with-eval-after-load}:
994 994
995@defun eval-after-load library form 995@defmac with-eval-after-load library body@dots{}
996This function arranges to evaluate @var{form} at the end of loading 996This macro arranges to evaluate @var{body} at the end of loading
997the file @var{library}, each time @var{library} is loaded. If 997the file @var{library}, each time @var{library} is loaded. If
998@var{library} is already loaded, it evaluates @var{form} right away. 998@var{library} is already loaded, it evaluates @var{body} right away.
999Don't forget to quote @var{form}!
1000 999
1001You don't need to give a directory or extension in the file name 1000You don't need to give a directory or extension in the file name
1002@var{library}. Normally, you just give a bare file name, like this: 1001@var{library}. Normally, you just give a bare file name, like this:
1003 1002
1004@example 1003@example
1005(eval-after-load "edebug" '(def-edebug-spec c-point t)) 1004(with-eval-after-load "edebug" (def-edebug-spec c-point t))
1006@end example 1005@end example
1007 1006
1008To restrict which files can trigger the evaluation, include a 1007To 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
1014@file{my_inst.el}: 1013@file{my_inst.el}:
1015 1014
1016@example 1015@example
1017(eval-after-load "foo/bar/my_inst.elc" @dots{}) 1016(with-eval-after-load "foo/bar/my_inst.elc" @dots{})
1018@end example 1017@end example
1019 1018
1020@var{library} can also be a feature (i.e., a symbol), in which case 1019@var{library} can also be a feature (i.e., a symbol), in which case
1021@var{form} is evaluated at the end of any file where 1020@var{body} is evaluated at the end of any file where
1022@code{(provide @var{library})} is called. 1021@code{(provide @var{library})} is called.
1023 1022
1024An error in @var{form} does not undo the load, but does prevent 1023An error in @var{body} does not undo the load, but does prevent
1025execution of the rest of @var{form}. 1024execution of the rest of @var{body}.
1026@end defun 1025@end defmac
1027 1026
1028Normally, well-designed Lisp programs should not use 1027Normally, well-designed Lisp programs should not use
1029@code{eval-after-load}. If you need to examine and set the variables 1028@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
1031it immediately---there is no need to wait until the library is loaded. 1030it immediately---there is no need to wait until the library is loaded.
1032If you need to call functions defined by that library, you should load 1031If you need to call functions defined by that library, you should load
1033the library, preferably with @code{require} (@pxref{Named Features}). 1032the library, preferably with @code{require} (@pxref{Named Features}).
1034
1035@defvar after-load-alist
1036This variable stores an alist built by @code{eval-after-load},
1037containing the expressions to evaluate when certain libraries are
1038loaded. Each element looks like this:
1039
1040@example
1041(@var{regexp-or-feature} @var{forms}@dots{})
1042@end example
1043
1044The key @var{regexp-or-feature} is either a regular expression or a
1045symbol, and the value is a list of forms. The forms are evaluated
1046when the key matches the absolute true name or feature name of the
1047library being loaded.
1048@end defvar
diff --git a/etc/NEWS b/etc/NEWS
index 44e4ada50cf..0501b4e97e2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -452,8 +452,9 @@ file using `set-file-extended-attributes'.
452 452
453* Lisp Changes in Emacs 24.4 453* Lisp Changes in Emacs 24.4
454 454
455FIXME - someone who knows what they are talking about, please improve 455+++
456this - see http://debbugs.gnu.org/14596 456** New macro with-eval-after-load. Like eval-after-load, but better behaved.
457
457** The default file coding for Emacs Lisp files is now utf-8. 458** The default file coding for Emacs Lisp files is now utf-8.
458(See file-coding-system-alist.) In most cases, this change is 459(See file-coding-system-alist.) In most cases, this change is
459totally transparent. Files that contain unusual characters but do 460totally transparent. Files that contain unusual characters but do
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 98e0382853d..88f218d15f3 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,11 @@
12013-06-13 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * subr.el (with-eval-after-load): New macro.
4 (eval-after-load): Allow form to be a function.
5 take advantage of lexical-binding.
6 (do-after-load-evaluation): Use dolist and adjust to new format.
7 * simple.el (bad-packages-alist): Use dolist and with-eval-after-load.
8
12013-06-13 Juri Linkov <juri@jurta.org> 92013-06-13 Juri Linkov <juri@jurta.org>
2 10
3 * replace.el (perform-replace): Display "symbol " and other search 11 * replace.el (perform-replace): Display "symbol " and other search
diff --git a/lisp/simple.el b/lisp/simple.el
index 15bf8779f56..3fd94e96d33 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -7295,8 +7295,7 @@ version and use the one distributed with Emacs."))
7295 "Alist of packages known to cause problems in this version of Emacs. 7295 "Alist of packages known to cause problems in this version of Emacs.
7296Each element has the form (PACKAGE SYMBOL REGEXP STRING). 7296Each element has the form (PACKAGE SYMBOL REGEXP STRING).
7297PACKAGE is either a regular expression to match file names, or a 7297PACKAGE is either a regular expression to match file names, or a
7298symbol (a feature name); see the documentation of 7298symbol (a feature name), like for `with-eval-after-load'.
7299`after-load-alist', to which this variable adds functions.
7300SYMBOL is either the name of a string variable, or `t'. Upon 7299SYMBOL is either the name of a string variable, or `t'. Upon
7301loading PACKAGE, if SYMBOL is t or matches REGEXP, display a 7300loading PACKAGE, if SYMBOL is t or matches REGEXP, display a
7302warning using STRING as the message.") 7301warning using STRING as the message.")
@@ -7314,10 +7313,10 @@ warning using STRING as the message.")
7314 (display-warning package (nth 3 list) :warning))) 7313 (display-warning package (nth 3 list) :warning)))
7315 (error nil))) 7314 (error nil)))
7316 7315
7317(mapc (lambda (elem) 7316(dolist (elem bad-packages-alist)
7318 (eval-after-load (car elem) `(bad-package-check ',(car elem)))) 7317 (let ((pkg (car elem)))
7319 bad-packages-alist) 7318 (with-eval-after-load pkg
7320 7319 (bad-package-check pkg))))
7321 7320
7322(provide 'simple) 7321(provide 'simple)
7323 7322
diff --git a/lisp/subr.el b/lisp/subr.el
index 380b2ba66ee..05f9167c699 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -3729,6 +3729,8 @@ Return nil if there isn't one."
3729(defun eval-after-load (file form) 3729(defun eval-after-load (file form)
3730 "Arrange that if FILE is loaded, FORM will be run immediately afterwards. 3730 "Arrange that if FILE is loaded, FORM will be run immediately afterwards.
3731If FILE is already loaded, evaluate FORM right now. 3731If FILE is already loaded, evaluate FORM right now.
3732FORM can be an Elisp expression (in which case it's passed to `eval'),
3733or a function (in which case it's passed to `funcall' with no argument).
3732 3734
3733If a matching file is loaded again, FORM will be evaluated again. 3735If a matching file is loaded again, FORM will be evaluated again.
3734 3736
@@ -3756,43 +3758,58 @@ Usually FILE is just a library name like \"font-lock\" or a feature name
3756like 'font-lock. 3758like 'font-lock.
3757 3759
3758This function makes or adds to an entry on `after-load-alist'." 3760This function makes or adds to an entry on `after-load-alist'."
3761 (declare (compiler-macro
3762 (lambda (whole)
3763 (if (eq 'quote (car-safe form))
3764 ;; Quote with lambda so the compiler can look inside.
3765 `(eval-after-load ,file (lambda () ,(nth 1 form)))
3766 whole))))
3759 ;; Add this FORM into after-load-alist (regardless of whether we'll be 3767 ;; Add this FORM into after-load-alist (regardless of whether we'll be
3760 ;; evaluating it now). 3768 ;; evaluating it now).
3761 (let* ((regexp-or-feature 3769 (let* ((regexp-or-feature
3762 (if (stringp file) 3770 (if (stringp file)
3763 (setq file (purecopy (load-history-regexp file))) 3771 (setq file (purecopy (load-history-regexp file)))
3764 file)) 3772 file))
3765 (elt (assoc regexp-or-feature after-load-alist))) 3773 (elt (assoc regexp-or-feature after-load-alist))
3774 (func
3775 (if (functionp form) form
3776 ;; Try to use the "current" lexical/dynamic mode for `form'.
3777 (eval `(lambda () ,form) lexical-binding))))
3766 (unless elt 3778 (unless elt
3767 (setq elt (list regexp-or-feature)) 3779 (setq elt (list regexp-or-feature))
3768 (push elt after-load-alist)) 3780 (push elt after-load-alist))
3769 ;; Make sure `form' is evalled in the current lexical/dynamic code.
3770 (setq form `(funcall ',(eval `(lambda () ,form) lexical-binding)))
3771 ;; Is there an already loaded file whose name (or `provide' name) 3781 ;; Is there an already loaded file whose name (or `provide' name)
3772 ;; matches FILE? 3782 ;; matches FILE?
3773 (prog1 (if (if (stringp file) 3783 (prog1 (if (if (stringp file)
3774 (load-history-filename-element regexp-or-feature) 3784 (load-history-filename-element regexp-or-feature)
3775 (featurep file)) 3785 (featurep file))
3776 (eval form)) 3786 (funcall func))
3777 (when (symbolp regexp-or-feature) 3787 (let ((delayed-func
3778 ;; For features, the after-load-alist elements get run when `provide' is 3788 (if (not (symbolp regexp-or-feature)) func
3779 ;; called rather than at the end of the file. So add an indirection to 3789 ;; For features, the after-load-alist elements get run when
3780 ;; make sure that `form' is really run "after-load" in case the provide 3790 ;; `provide' is called rather than at the end of the file.
3781 ;; call happens early. 3791 ;; So add an indirection to make sure that `func' is really run
3782 (setq form 3792 ;; "after-load" in case the provide call happens early.
3783 `(if load-file-name 3793 (lambda ()
3784 (let ((fun (make-symbol "eval-after-load-helper"))) 3794 (if (not load-file-name)
3785 (fset fun `(lambda (file) 3795 ;; Not being provided from a file, run func right now.
3786 (if (not (equal file ',load-file-name)) 3796 (funcall func)
3787 nil 3797 (let ((lfn load-file-name))
3788 (remove-hook 'after-load-functions ',fun) 3798 (letrec ((fun (lambda (file)
3789 ,',form))) 3799 (when (equal file lfn)
3790 (add-hook 'after-load-functions fun)) 3800 (remove-hook 'after-load-functions fun)
3791 ;; Not being provided from a file, run form right now. 3801 (funcall func)))))
3792 ,form))) 3802 (add-hook 'after-load-functions fun))))))))
3793 ;; Add FORM to the element unless it's already there. 3803 ;; Add FORM to the element unless it's already there.
3794 (unless (member form (cdr elt)) 3804 (unless (member delayed-func (cdr elt))
3795 (nconc elt (list form)))))) 3805 (nconc elt (list delayed-func)))))))
3806
3807(defmacro with-eval-after-load (file &rest body)
3808 "Execute BODY after FILE is loaded.
3809FILE is normally a feature name, but it can also be a file name,
3810in case that file does not provide any feature."
3811 (declare (indent 1) (debug t))
3812 `(eval-after-load ,file (lambda () ,@body)))
3796 3813
3797(defvar after-load-functions nil 3814(defvar after-load-functions nil
3798 "Special hook run after loading a file. 3815 "Special hook run after loading a file.
@@ -3804,12 +3821,11 @@ name of the file just loaded.")
3804ABS-FILE, a string, should be the absolute true name of a file just loaded. 3821ABS-FILE, a string, should be the absolute true name of a file just loaded.
3805This function is called directly from the C code." 3822This function is called directly from the C code."
3806 ;; Run the relevant eval-after-load forms. 3823 ;; Run the relevant eval-after-load forms.
3807 (mapc #'(lambda (a-l-element) 3824 (dolist (a-l-element after-load-alist)
3808 (when (and (stringp (car a-l-element)) 3825 (when (and (stringp (car a-l-element))
3809 (string-match-p (car a-l-element) abs-file)) 3826 (string-match-p (car a-l-element) abs-file))
3810 ;; discard the file name regexp 3827 ;; discard the file name regexp
3811 (mapc #'eval (cdr a-l-element)))) 3828 (mapc #'funcall (cdr a-l-element))))
3812 after-load-alist)
3813 ;; Complain when the user uses obsolete files. 3829 ;; Complain when the user uses obsolete files.
3814 (when (string-match-p "/obsolete/[^/]*\\'" abs-file) 3830 (when (string-match-p "/obsolete/[^/]*\\'" abs-file)
3815 (run-with-timer 0 nil 3831 (run-with-timer 0 nil
diff --git a/src/ChangeLog b/src/ChangeLog
index 4d6e669612f..827092e7f8a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
12013-06-13 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * lread.c (syms_of_lread):
4 * fns.c (Fprovide): Adjust to new format of after-load-alist.
5
12013-06-13 Kelly Dean <kellydeanch@yahoo.com> (tiny change) 62013-06-13 Kelly Dean <kellydeanch@yahoo.com> (tiny change)
2 7
3 * fileio.c (Fdo_auto_save): Trap errors in auto-save-hook. (Bug#14479) 8 * fileio.c (Fdo_auto_save): Trap errors in auto-save-hook. (Bug#14479)
diff --git a/src/fns.c b/src/fns.c
index 08c6f055f38..06d4e358f10 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2545,6 +2545,8 @@ SUBFEATURE can be used to check a specific subfeature of FEATURE. */)
2545 return (NILP (tem)) ? Qnil : Qt; 2545 return (NILP (tem)) ? Qnil : Qt;
2546} 2546}
2547 2547
2548static Lisp_Object Qfuncall;
2549
2548DEFUN ("provide", Fprovide, Sprovide, 1, 2, 0, 2550DEFUN ("provide", Fprovide, Sprovide, 1, 2, 0,
2549 doc: /* Announce that FEATURE is a feature of the current Emacs. 2551 doc: /* Announce that FEATURE is a feature of the current Emacs.
2550The optional argument SUBFEATURES should be a list of symbols listing 2552The optional argument SUBFEATURES should be a list of symbols listing
@@ -2567,7 +2569,7 @@ particular subfeatures supported in this version of FEATURE. */)
2567 /* Run any load-hooks for this file. */ 2569 /* Run any load-hooks for this file. */
2568 tem = Fassq (feature, Vafter_load_alist); 2570 tem = Fassq (feature, Vafter_load_alist);
2569 if (CONSP (tem)) 2571 if (CONSP (tem))
2570 Fprogn (XCDR (tem)); 2572 Fmapc (Qfuncall, XCDR (tem));
2571 2573
2572 return feature; 2574 return feature;
2573} 2575}
@@ -4866,6 +4868,7 @@ syms_of_fns (void)
4866Used by `featurep' and `require', and altered by `provide'. */); 4868Used by `featurep' and `require', and altered by `provide'. */);
4867 Vfeatures = Fcons (intern_c_string ("emacs"), Qnil); 4869 Vfeatures = Fcons (intern_c_string ("emacs"), Qnil);
4868 DEFSYM (Qsubfeatures, "subfeatures"); 4870 DEFSYM (Qsubfeatures, "subfeatures");
4871 DEFSYM (Qfuncall, "funcall");
4869 4872
4870#ifdef HAVE_LANGINFO_CODESET 4873#ifdef HAVE_LANGINFO_CODESET
4871 DEFSYM (Qcodeset, "codeset"); 4874 DEFSYM (Qcodeset, "codeset");
diff --git a/src/lread.c b/src/lread.c
index 3ca644bb45b..b57665e365c 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -4485,15 +4485,15 @@ customize `jka-compr-load-suffixes' rather than the present variable. */);
4485 DEFSYM (Qload_in_progress, "load-in-progress"); 4485 DEFSYM (Qload_in_progress, "load-in-progress");
4486 4486
4487 DEFVAR_LISP ("after-load-alist", Vafter_load_alist, 4487 DEFVAR_LISP ("after-load-alist", Vafter_load_alist,
4488 doc: /* An alist of expressions to be evalled when particular files are loaded. 4488 doc: /* An alist of functions to be evalled when particular files are loaded.
4489Each element looks like (REGEXP-OR-FEATURE FORMS...). 4489Each element looks like (REGEXP-OR-FEATURE FUNCS...).
4490 4490
4491REGEXP-OR-FEATURE is either a regular expression to match file names, or 4491REGEXP-OR-FEATURE is either a regular expression to match file names, or
4492a symbol \(a feature name). 4492a symbol \(a feature name).
4493 4493
4494When `load' is run and the file-name argument matches an element's 4494When `load' is run and the file-name argument matches an element's
4495REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol 4495REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol
4496REGEXP-OR-FEATURE, the FORMS in the element are executed. 4496REGEXP-OR-FEATURE, the FUNCS in the element are called.
4497 4497
4498An error in FORMS does not undo the load, but does prevent execution of 4498An error in FORMS does not undo the load, but does prevent execution of
4499the rest of the FORMS. */); 4499the rest of the FORMS. */);