eval-after-provision

Brian Palmer <[email protected]> 24 Mar 2004 10:02:01 -0800
Newsgroups gmane.emacs.xemacs.design
Message-ID <[email protected]>
I've been working for a while with a feature 'eval-after-provision' in
my init file which seems like it'd be a useful feature to integrate
into xemacs. From the comments in the source for eval-after-load and
eval-when-feature, it seems like others agree with me. To summarize,
the trouble with e-a-l and e-w-f is that they work with
after-load-alist. However, there are different names under which a
file can be loaded, which makes an alist a problematic structure to
use. Furthermore, in theory features provide for filename
independence, but without a mechanism for evaluating forms after a
feature has been provided, a user has to be aware of what files are
going to be loaded that could provide the feature.

This is fairly straightforward; but it's sort of nasty, since it's
advising provide. It seems like it might be better to modify provide
in fns.c directly. I'd be interested in any feedback, of course.


(defvar eval-after-provision-alist nil
  "Alist mapping features to functions that should be invoked the
feature is provided. That is, entries are of the form 
(SYMBOL F1 F2 ... ) where each Fn accepts one argument, the SYMBOL
being provided. See eval-after-provision.")

(defun eval-after-provision (symbol form)
  "Arrange that, if SYMBOL is ever provided, that FORM will be
executed. When FORM is evaluated, SYMBOL will contain the feature
being provided. FORM can also be the name of a function expecting one
argument (the feature being provided). If the feature has already been
provided, FORM is evaluated immediately."
  (let ((existing-funs (assq symbol eval-after-provision-alist))
        (eval-fun (cond ((symbolp form) form)
                        (t              `(lambda (symbol) ,form)))))
    ;; If the feature's been provided already, immediately evaluate
    (if (featurep symbol)   
        (funcall eval-fun symbol)
      ;; otherwise, stash it for later
      (if existing-funs
          (nconc existing-funs (list eval-fun))
        (setq eval-after-provision-alist
              (cons (list symbol eval-fun) eval-after-provision-alist))))))

(defadvice provide (after support-eval-after-provision (feature)
activate)
  "Run any forms that should be evaluated after FEATURE is
provided. These forms, if any, are stored in
eval-after-provision-alist. After evaluation, the entries associated
with SYMBOL will be removed"
  (let* ((l (assq feature eval-after-provision-alist))
         (fs (cdr l)))
    (while fs
      (funcall (car fs) feature)
      (setq fs (cdr fs)))
    (setq eval-after-provision-alist (delete l eval-after-provision-alist))))

-- 
I'm awfully glad I'm a Beta, because I don't work so hard.