[comp.emacs] Changing dired functions without copying

sane@cs.uiuc.edu (Aamod Sane) (11/21/90)

I wanted to change dired functions such as dired-find-file to work 
with epoch. I have right now altered them in my own copy of dired.el.

The reason is that if I just put them in the .emacs, they
get overwritten when dired.el get loaded later.

Is there a way of catching the loading of dired, and then executing
these function definitions so that I do not have to make a copy
of dired.el? 
(without, of couse loading dired first and then executing these
 functions in the .emacs (why load it if I wont use it?))


Thanks

Aamod Sane
-- 
sane@cs.uiuc.edu
         ==         / \  
-----    ==    *    \_/     -|||- 
         ==     

Mike.Williams@comp.vuw.ac.nz (Mike Williams) (11/21/90)

+-- sane@cs.uiuc.edu (Aamod Sane) writes:
| 
| I wanted to change dired functions such as dired-find-file to work 
| with epoch. I have right now altered them in my own copy of dired.el.
| 
| The reason is that if I just put them in the .emacs, they
| get overwritten when dired.el get loaded later.
| 
| Is there a way of catching the loading of dired, and then executing
| these function definitions so that I do not have to make a copy
| of dired.el? 

    What I do is to put the dired-mode setup code in a separate file (eg.
  dired-setup.el).  Along with all the setup stuff, I define the function
  'dired-mode-hook.  It's then quite easy to get this function (and hence
  the rest of the setup file) to autoload when dired is first used, like
  so: 

      (setq dired-mode-hook 'dired-mode-hook)
      (autoload 'dired-mode-hook "dired-setup")

    Note that the 'dired-mode-hook function doesn't actually have to do
  anything - it's primary purpose is to act as a autoload trigger.  This is
  a general technique for loading mode-specific setup code.  For key
  bindings, function re-definitions etc., it's better than putting them
  inside a mode-hook, as the code is only run once.        

    Also, you can ensure that your setup code is only run *after* loading
  dired, by putting 

      (require 'dired)

  at the top of the dired-setup.el file.

--
      /-------------------- byrd@comp.vuw.ac.nz --------------------\ 
      | Mike Williams, Victoria University of Wellington, Aotearoa. |
      \-------- Yesterday, I ... no, wait, that wasn't me. ---------/

liberte@cs.uiuc.edu (Daniel LaLiberte) (11/21/90)

The problem of "shadowing" function definitions in emacs has not
been solved in a publically standard way yet.  I propose a solution below.

Here is the problem:

+-- sane@cs.uiuc.edu (Aamod Sane) writes:
| Is there a way of catching the loading of dired, and then executing
| these function definitions so that I do not have to make a copy
| of dired.el? 

From: Mike.Williams@comp.vuw.ac.nz (Mike Williams)
    What I do is to put the dired-mode setup code in a separate file (eg.
  dired-setup.el).  Along with all the setup stuff, I define the function
  'dired-mode-hook.  It's then quite easy to get this function (and hence
  the rest of the setup file) to autoload when dired is first used, like
  so: 
-----

A more general scheme of "shadowing" definitions than depending on a
-hook for each file would be something like the following:

1. Name your file of shadow definitions with the same name as the
   file with the standard definitions, but put it in a different
   directory that is earlier on your load-path.  Thus it will be
   loaded first.

2. At the top of your shadow definitions, do the following:

   (require 'shadow)
   (shadow-load)

3. Follow with your shadow definitions.

The shadow-load function should temporarily modify the load-path to
exclude all the directories up to the directory that the current file
is in, and then just do load again on the same file name.
Unfortunately, the file name and directory of the file being loaded is
not available, so the load function itself will have to be shadowed
too to provide this information, or the call of shadow-load could
provide this explicitly - with less portability,
e.g. (shadow-load "foo-mode" "my-stuff").

I invite comments on this scheme, or the problem in general.

Dan LaLiberte
uiucdcs!liberte
liberte@cs.uiuc.edu
liberte%a.cs.uiuc.edu@uiucvmd.bitnet

mic@theory.lcs.mit.edu (Michelangelo Grigni) (11/21/90)

From Daniel LaLiberte <LIBERTE.90Nov20205617@clitus.cs.uiuc.edu>:

> A more general scheme of "shadowing" definitions than depending on a
> -hook for each file would be something like the following:
>
> 1. Name your file of shadow definitions with the same name as the
>    file with the standard definitions, but put it in a different
>    directory that is earlier on your load-path.  Thus it will be
>    loaded first.
> ...
> I invite comments on this scheme, or the problem in general.

Yes, I've used this kind of scheme for a couple of years, it has the
advantage that shadowed modes are not explicitly mentioned in
your ~/.emacs, so you do not have to go changing .emacs nearly as
often; rather you go change the appropriate "shadow file".

It has the disadvantage that your shadowed definitions may no longer
be appropriate if the 'default' source is updated, and they will be
ignored if emacs is rebuilt with such packages preloaded.

How: early in ~/.emacs I define a default-load function, which loads
using the startup value of load-path.  I then modify the load-path to
start with my shadowing directory ~/el.  All my shadowing files then
look something like (eg "~/el/dired.el"):

 (default-load "dired")
 (defvar ...) ... (defun ...) ...

This scheme is complicated by the fact that while default-load'ing the
file, I still want load-path bound to my expanded path, in case the
default file triggers the loading of further packages.

Relevant ~/.emacs code appended (best byte-compiled).  I make the
comment that this would be cleaner if a <subr> version of
expand-load-file-name were available from inside elisp.

--- Michelangelo Grigni

;; -*- emacs-lisp -*-
(defvar default-load-path load-path "Startup value of load-path.")
(setq
 load-path 
 (apply 
  'nconc
  (mapcar 
   (function 
    (lambda (dir) 
      (if (file-directory-p dir) 
	  (list (expand-file-name dir)))))
   (append 
    ;; higher priority directories:
    '("~/el" "~/el/gnus" "/a/aviary/emacs")
    ;; default directories:
    default-load-path 
    ;; lower priority directories:
    '("~bard/emacs")
    ))))

(defun expand-load-file-name (file &optional no-suff path) "\
Find full name of FILE that (load FILE) would load, or nil if none.
Optional second argument NO-SUFF is like the optional fourth argument for
load, i.e. don't try adding suffixes \".elc\" and \".el\".  
Optional third argument PATH specifies a different search path (the default
is load-path)."
  (or path (setq path load-path))
  (if (file-name-absolute-p file)
      (setq path (list (file-name-directory file))
	    file (file-name-nondirectory file)))
  (let ((suffixes-to-try
	 (cond
	  ((consp no-suff) no-suff) ;; undocumented hook here
	  ((or no-suff (string-match "\\.elc?$" file)) '(""))
	  (t '(".elc" ".el")))))
    (let (found suffixes)
      (while (and path (not found))
	(setq suffixes suffixes-to-try)
	(while (and suffixes (not found))
	  (let ((try (expand-file-name 
		      (concat file (car suffixes))
		      (car path))))
	    (if (file-exists-p try)
		(setq found try)))
	  (setq suffixes (cdr suffixes)))
	(setq path (cdr path)))
      found)))
	    
;; Examples:
;; (expand-load-file-name "x-mouse")
;; (expand-load-file-name "term/vt100")
;; (expand-load-file-name "term/vt100" nil default-load-path)

(defun default-load (file &optional miss-ok no-mess no-suff bind) "\
Load FILE using default-load-path as load-path.  The remaining optional
arguments are the same as for load, except the new optional fifth argument
BIND non-nil means to dynamically bind load-path to default-load-path
during the load (this may matter to recursive loads)."
  (let ((fullname (expand-load-file-name file no-suff default-load-path)))
    (if fullname
	(if bind
	    (let ((load-path default-load-path))
	      (load fullname nil no-mess t))
	  (load fullname nil no-mess t))
      (or miss-ok (error "Cannot open default-load file: %s" file))
      nil)))

(defun distrib-load (file &optional miss-ok no-mess no-suff) "\
Load FILE from the distribution ../lisp directory.  Remaining optional
arguments are the same as for load."
  (load (expand-file-name file (expand-file-name "../lisp" exec-directory))
	miss-ok no-mess no-suff))
--
Michelangelo Grigni  253-1365  NE43-346