emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r112976: * lisp/subr.el (with-eval-after-load): New


From: Stefan Monnier
Subject: [Emacs-diffs] trunk r112976: * lisp/subr.el (with-eval-after-load): New macro.
Date: Thu, 13 Jun 2013 22:25:11 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 112976
revision-id: address@hidden
parent: address@hidden
committer: Stefan Monnier <address@hidden>
branch nick: trunk
timestamp: Thu 2013-06-13 18:24:52 -0400
message:
  * 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.
modified:
  doc/lispref/ChangeLog          changelog-20091113204419-o5vbwnq5f7feedwu-6155
  doc/lispref/loading.texi       
loading.texi-20091113204419-o5vbwnq5f7feedwu-6193
  etc/NEWS                       news-20100311060928-aoit31wvzf25yr1z-1
  lisp/ChangeLog                 changelog-20091113204419-o5vbwnq5f7feedwu-1432
  lisp/simple.el                 simple.el-20091113204419-o5vbwnq5f7feedwu-403
  lisp/subr.el                   subr.el-20091113204419-o5vbwnq5f7feedwu-151
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/fns.c                      fns.c-20091113204419-o5vbwnq5f7feedwu-203
  src/lread.c                    lread.c-20091113204419-o5vbwnq5f7feedwu-266
=== modified file 'doc/lispref/ChangeLog'
--- a/doc/lispref/ChangeLog     2013-06-11 11:37:56 +0000
+++ b/doc/lispref/ChangeLog     2013-06-13 22:24:52 +0000
@@ -1,3 +1,8 @@
+2013-06-13  Stefan Monnier  <address@hidden>
+
+       * 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  <address@hidden>
 
        * files.texi (File Name Expansion): Make the example more

=== modified file 'doc/lispref/loading.texi'
--- a/doc/lispref/loading.texi  2013-05-15 20:12:53 +0000
+++ b/doc/lispref/loading.texi  2013-06-13 22:24:52 +0000
@@ -990,19 +990,18 @@
 @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}:
 
address@hidden eval-after-load library form
-This function arranges to evaluate @var{form} at the end of loading
address@hidden with-eval-after-load library address@hidden
+This macro arranges to evaluate @var{body} at the end of loading
 the file @var{library}, each time @var{library} is loaded.  If
address@hidden is already loaded, it evaluates @var{form} right away.
-Don't forget to quote @var{form}!
address@hidden 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 @@
 @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
address@hidden is evaluated at the end of any file where
address@hidden 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}.
address@hidden defun
+An error in @var{body} does not undo the load, but does prevent
+execution of the rest of @var{body}.
address@hidden 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 @@
 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}).
-
address@hidden 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:
-
address@hidden
-(@var{regexp-or-feature} @address@hidden)
address@hidden 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.
address@hidden defvar

=== modified file 'etc/NEWS'
--- a/etc/NEWS  2013-06-13 21:49:10 +0000
+++ b/etc/NEWS  2013-06-13 22:24:52 +0000
@@ -452,8 +452,9 @@
 
 * 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

=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2013-06-13 22:08:45 +0000
+++ b/lisp/ChangeLog    2013-06-13 22:24:52 +0000
@@ -1,3 +1,11 @@
+2013-06-13  Stefan Monnier  <address@hidden>
+
+       * 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  <address@hidden>
 
        * replace.el (perform-replace): Display "symbol " and other search

=== modified file 'lisp/simple.el'
--- a/lisp/simple.el    2013-06-05 18:10:27 +0000
+++ b/lisp/simple.el    2013-06-13 22:24:52 +0000
@@ -7295,8 +7295,7 @@
   "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 @@
              (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)
 

=== modified file 'lisp/subr.el'
--- a/lisp/subr.el      2013-06-13 20:43:53 +0000
+++ b/lisp/subr.el      2013-06-13 22:24:52 +0000
@@ -3729,6 +3729,8 @@
 (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 @@
 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 @@
 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

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-06-13 05:13:05 +0000
+++ b/src/ChangeLog     2013-06-13 22:24:52 +0000
@@ -1,3 +1,8 @@
+2013-06-13  Stefan Monnier  <address@hidden>
+
+       * lread.c (syms_of_lread):
+       * fns.c (Fprovide): Adjust to new format of after-load-alist.
+
 2013-06-13  Kelly Dean  <address@hidden>  (tiny change)
 
        * fileio.c (Fdo_auto_save): Trap errors in auto-save-hook.  (Bug#14479)

=== modified file 'src/fns.c'
--- a/src/fns.c 2013-04-08 18:04:58 +0000
+++ b/src/fns.c 2013-06-13 22:24:52 +0000
@@ -2545,6 +2545,8 @@
   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 @@
   /* 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 @@
 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");

=== modified file 'src/lread.c'
--- a/src/lread.c       2013-05-15 20:12:53 +0000
+++ b/src/lread.c       2013-06-13 22:24:52 +0000
@@ -4485,15 +4485,15 @@
   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.  */);


reply via email to

[Prev in Thread] Current Thread [Next in Thread]