emacs-devel
[Top][All Lists]
Advanced

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

eval-after-load as a macro (and eval-next-after-load)


From: Stefan Monnier
Subject: eval-after-load as a macro (and eval-next-after-load)
Date: Fri, 04 Apr 2003 15:30:14 -0500

eval-after-load is currently a function and is thus pretty much always
used as follows:

        (eval-after-load "foobar"
          '(some code))

Now, how about turning it into a macro so we can just write:

        (eval-after-load "foobar"
          (some code))

Of course, such a change would introduce an incompatibility,
but it turns out that I think it's rather minor.  We can detect
the case where the argument is of the form (quote ...) and
treat it as it was before.  That takes care of 98% of the
case.   Of the remaining 2% of the cases, the current Emacs
sources have two cases:

- the macro would break things.  This only happens once in Emacs,
  more specifically in

        (defun eval-next-after-load (file)
          "Read the following input sexp, and run it whenever FILE is loaded.
        This makes or adds to an entry on `after-load-alist'.
        FILE should be the name of a library, with no directory name."
          (eval-after-load file (read)))

  that's the only place I could find where the expression passed
  to eval-after-load is not a constant.  Note that eval-next-after-load
  is never used in Emacs and that a google search only turned up
  XEmacs code that adds compatibility support for Emacs'
  eval-after-load and eval-next-after-load: no uses.

- The macro would fix things because the author didn't realize
  what was going on and wrote (eval-after-load "foo" (some code))
  without the quote.  Such a bug was recently fixed in crisp.el
  but there's still a few occurrences in viper.el (luckily those
  occurences don't matter because they only contain defadvice
  which works either way anyway).

So I suggest we make eval-next-after-load obsolete and turn
eval-after-load into a macro that emulates the function behavior
in the special case that the second arg is a quoted expression.

See sample patch below,


        Stefan



--- subr.el     3 Apr 2003 23:13:38 -0000       1.347
+++ subr.el     4 Apr 2003 20:21:49 -0000
@@ -951,7 +977,7 @@
 
 ;;;; Specifying things to do after certain files are loaded.
 
-(defun eval-after-load (file form)
+(defun eval-after-load-internal (file form)
   "Arrange that, if FILE is ever loaded, FORM will be run at that time.
 This makes or adds to an entry on `after-load-alist'.
 If FILE is already loaded, evaluate FORM right now.
@@ -977,11 +1003,29 @@
          (eval form))))
   form)
 
+(defmacro eval-after-load (file &rest code)
+  "Arrange that, if FILE is ever loaded, CODE will be run at that time.
+This makes or adds to an entry on `after-load-alist'.
+If FILE is already loaded, evaluate FORM right now.
+It does nothing if CODE is already on the list for FILE.
+FILE must match exactly.  Normally FILE is the name of a library,
+with no directory or extension specified, since that is how `load'
+is normally called.
+FILE can also be a feature (i.e. a symbol), in which case FORM is
+evaluated whenever that feature is `provide'd."
+  (declare (indent 1) (debug t))
+  (when (consp code)
+    (if (and (null (cdr code))
+            (memq (car-safe (car code)) '(quote \`)))
+       `(eval-after-load-internal ,file ,(car code))
+      `(eval-after-load-internal ,file '(progn ,@code)))))
+
 (defun eval-next-after-load (file)
   "Read the following input sexp, and run it whenever FILE is loaded.
 This makes or adds to an entry on `after-load-alist'.
 FILE should be the name of a library, with no directory name."
-  (eval-after-load file (read)))
+  (eval `(eval-after-load file ,(read))))
+(make-obsolete 'eval-next-after-load 'eval-after-load "21.4")
 
 ;;; make-network-process wrappers
 





reply via email to

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