emacs-devel
[Top][All Lists]
Advanced

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

Re: file-relative-name and remote files


From: Stefan Monnier
Subject: Re: file-relative-name and remote files
Date: Sun, 23 Feb 2003 13:30:43 -0500

> > IMHO, the following might work: file-relative-name finds a filename 
> > handler for the filename and one for the directory. If they are 
> > different, then the two must come from different handlers, so do like 
> > the different-drives case. If they are equal, invoke the handler. This 
> > requires a new file operation, file-relative-name. It seems to work 
> > for Ange-FTP and Tramp. However... Imagine that there was a filename 
> > handler which could look inside of tar files, so that the filename 
> > /tmp/foo.tar/x/y would extract the file x/y from the tarball 
> > /tmp/foo.tar. So should (file-relative-name "/tmp/foo.tar/x/y" "/tmp") 
> > eval to "foo.tar/x/y" or not?
> 
> 
> What about changing it to:
> file-relative-name finds a filename handler for the filename and one for
> the directory. If they are non-nil and different, then the two must come
> from different handlers, so do like the different-drives case. If they
> are non-nil and equal, or one is non-nil and the other nil, invoke the
> handler. If both are nil, execute the build in code.

How about something like:

   (defun f-r-n (filename &optional directory)
     (let* ((dir (if directory (expand-file-name directory) default-directory))
            (file (expand-file-name (file-name-directory filename)))
            (hf (find-file-name-handler file 'file-relative-name))
            (hd (find-file-name-handler dir 'file-relative-name)))
       (cond
        ((not (eq hf hd))
         ;; `filename' and `directory' are on different drives:
         ;; there is hence no relative name from `directory' to `filename'.
         (expand-file-name filename))
        ((null hf)
         ;; Both are plain local: use the builtin code.
         (file-relative-name filename directory))
        ((let ((re (car (rassq hf file-name-handler-alist))))
           (equal (and (string-match re file) (substring file 0 (match-end 0)))
                  (and (string-match re dir) (substring dir 0 (match-end 0)))))
         ;; Both are non-local, use the same handler and same drive name.       
   
         (file-relative-name filename directory))
        (t
         ;; Both are non-local and on different drives.
         (expand-file-name filename)))))

Note how I check the handler for (file-name-directory filename) rather
than for `filename' so as to avoid uselessly catching jka-compr-style
handlers.


        Stefan





reply via email to

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