From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Dave Love Newsgroups: gmane.emacs.bugs Subject: Re: the ...-unload-hook convention doesn't work Date: Mon, 12 Jan 2004 15:23:51 +0000 Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Message-ID: References: <200401051824.i05IOpP07535@raven.dms.auburn.edu> <200401091708.i09H8YU13964@raven.dms.auburn.edu> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1073930996 17098 80.91.224.253 (12 Jan 2004 18:09:56 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Mon, 12 Jan 2004 18:09:56 +0000 (UTC) Cc: bug-gnu-emacs@gnu.org, rms@gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Jan 12 19:09:51 2004 Return-path: Original-Received: from monty-python.gnu.org ([199.232.76.173]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1Ag6Vb-0004Wx-00 for ; Mon, 12 Jan 2004 19:09:51 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.24) id 1Ag73o-0003x3-0e for geb-bug-gnu-emacs@m.gmane.org; Mon, 12 Jan 2004 13:45:12 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.24) id 1Ag53K-0004L2-23 for bug-gnu-emacs@gnu.org; Mon, 12 Jan 2004 11:36:34 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.24) id 1Ag52n-00044g-AB for bug-gnu-emacs@gnu.org; Mon, 12 Jan 2004 11:36:32 -0500 Original-Received: from [148.79.80.39] (helo=albion.dl.ac.uk) by monty-python.gnu.org with esmtp (Exim 4.24) id 1Ag4so-000100-G5; Mon, 12 Jan 2004 11:25:42 -0500 Original-Received: from fx by albion.dl.ac.uk with local (Exim 3.35 #1 (Debian)) id 1Ag3ux-0004xS-00; Mon, 12 Jan 2004 15:23:51 +0000 Original-To: Luc Teirlinck User-Agent: Gnus/5.1005 (Gnus v5.10.5) Emacs/21.2 (gnu/linux) X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.1.2 Precedence: list List-Id: Bug reports for GNU Emacs, the Swiss army knife of text editors List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: main.gmane.org gmane.emacs.bugs:6543 X-Report-Spam: http://spam.gmane.org/gmane.emacs.bugs:6543 Luc Teirlinck writes: > I can not but wonder what we exactly want to achieve with `unload-feature'. > Is there any hope of ever making it safe enough to be called in an > actual editing session in which non-trivial work is invested and will > _continue_ to be invested after unloading a feature? Yes, with code that obeys the Emacs conventions in the Lisp manual. I frequently use it, which is why I worked on it initially. > I do not believe > that it currently comes even remotely close to that standard. > > The worst thing is that even reloading the feature often can not undo > the damage: > > ELISP> (fboundp 'macroexpand) > t > ELISP> (require 'cl) > cl > ELISP> (fboundp 'macroexpand) > t > ELISP> (unload-feature 'cl) ;; Long output flushed > ELISP> (require 'cl) > cl > ELISP> (fboundp 'macroexpand) > nil > ELISP> One of the conventions is to avoid CL at runtime. Another one is not to redefine Emacs functions as CL does. The package probably could actually make itself sanely unloadable by using the -unload-hook feature if anyone cared to work on it. In the event that a package has done something like this, it should have a documented way to fiddle the feature list to control what gets unbound. I realized that when dealing with code that needs to redefine several things which are currently problematic in Emacs and would eventually have got round to suggesting the following. (You can currently do it knowing that `flist' is the right name until someone changed that.) --- loadhist.el.~1.26.~ Mon Oct 6 11:55:29 2003 +++ loadhist.el Mon Jan 12 15:15:34 2004 @@ -120,7 +120,17 @@ (defun unload-feature (feature &optional force) "Unload the library that provided FEATURE, restoring all its autoloads. If the feature is required by any other loaded code, and prefix arg FORCE -is nil, raise an error." +is nil, raise an error. + +This function tries to undo modifications made by the package to +hooks. Packages may define a hook FEATURE-unload-hook that is called +instead of the normal heuristics for doing this. Such a hook should +undo all the relevant global state changes that may have been made by +loading the package or executing functions in it. It has access to +the package's feature list (before anything is unbound) in the +variable `feature-list' and could remove features from it in the event +that the package has done something normally-ill-advised, such as +redefining an Emacs function." (interactive (list (read-feature "Feature: ") current-prefix-arg)) (if (not (featurep feature)) (error "%s is not a currently loaded feature" (symbol-name feature))) @@ -130,8 +140,8 @@ (if dependents (error "Loaded libraries %s depend on %s" (prin1-to-string dependents) file)))) - (let* ((flist (feature-symbols feature)) - (file (car flist)) + (let* ((feature-list (feature-symbols feature)) + (file (car feature-list)) (unload-hook (intern-soft (concat (symbol-name feature) "-unload-hook")))) ;; Try to avoid losing badly when hooks installed in critical @@ -155,10 +165,10 @@ (string-match "-hooks?\\'" (symbol-name x))) (and (boundp x) ; Known abnormal hooks etc. (memq x unload-feature-special-hooks))) - (dolist (y (cdr flist)) + (dolist (y (cdr feature-list)) (remove-hook x y)))))) (if (fboundp 'elp-restore-function) ; remove ELP stuff first - (dolist (elt (cdr flist)) + (dolist (elt (cdr feature-list)) (if (symbolp elt) (elp-restore-function elt)))) (mapc @@ -183,7 +193,7 @@ (fmakunbound x) (let ((aload (get x 'autoload))) (if aload (fset x (cons 'autoload aload)))))))) - (cdr flist)) + (cdr feature-list)) ;; Delete the load-history element for this file. (let ((elt (assoc file load-history))) (setq load-history (delq elt load-history)))))