help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: make-auto-save-file-name: not using name transforms for mere buffers


From: Florian von Savigny
Subject: Re: make-auto-save-file-name: not using name transforms for mere buffers
Date: 12 Dec 2003 02:19:30 +0100
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2

Newsgroups: gnu.emacs.help
Subject: Re: make-auto-save-file-name: not using name transforms for mere       
buffers
References: <address@hidden> <address@hidden> <address@hidden> <address@hidden>
From: Florian von Savigny <address@hidden>
--text follows this line--

Eli Zaretskii <address@hidden> writes:

> > Wow, thanks for this hint; it does sound like a sane approach. But I
> > still need to understand when, in the particular case of auto-save
> > file names derived from buffer names, convert-standard-file-name takes
> > effect. AFAICS, it is not called directly from within
> > make-auto-save-file-name.
> 
> It _is_ called directly, at least in my version of Emacs, albeit only
> for non-Unix platforms.  

So is it one of msdos-long-file-names or dos-8+3-filename which calls
it? These were non-operational, undefined functions (presumably not
loaded) when running under Linux.

> But that should be easy to fix: simply modify the condition under
> which make-auto-save-file-name calls convert-standard-file-name.

I couldn't spot it called under any condition (neither directly nor
indirectly), but maybe I am overlooking something:

(defun make-auto-save-file-name ()
  "Return file name to use for auto-saves of current buffer.
Does not consider `auto-save-visited-file-name' as that variable is checked
before calling this function.  You can redefine this for customization.
See also `auto-save-file-name-p'."
  (if buffer-file-name
      (let ((list auto-save-file-name-transforms)
            (filename buffer-file-name)
            result)
        ;; Apply user-specified translations
        ;; to the file name.
        (while (and list (not result))
          (if (string-match (car (car list)) filename)
              (setq result (replace-match (cadr (car list)) t nil
                                          filename)))
          (setq list (cdr list)))
        (if result (setq filename result))

        (if (and (eq system-type 'ms-dos)
                 (not (msdos-long-file-names)))
            ;; We truncate the file name to DOS 8+3 limits before
            ;; doing anything else, because the regexp passed to
            ;; string-match below cannot handle extensions longer than
            ;; 3 characters, multiple dots, and other atrocities.
            (let ((fn (dos-8+3-filename
                       (file-name-nondirectory buffer-file-name))))
              (string-match "\\`\\([^.]+\\)\\(\\.\\(..?\\)?.?\\|\\)\\'" fn)
              (concat (file-name-directory buffer-file-name)
                      "#" (match-string 1 fn)
                      "." (match-string 3 fn) "#"))
          (concat (file-name-directory filename)
                  "#"
                  (file-name-nondirectory filename)
                  "#")))
    ;; else part of the if buffer-file-name:
    ;; Deal with buffers that don't have any associated files.  (Mail
    ;; mode tends to create a good number of these.)

    (let ((buffer-name (buffer-name))
          (limit 0))
      ;; Eliminate all slashes and backslashes by
      ;; replacing them with sequences that start with %.
      ;; Quote % also, to keep distinct names distinct.
      (while (string-match "[/\\%]" buffer-name limit)
        (let* ((character (aref buffer-name (match-beginning 0)))
               (replacement
                (cond ((eq character ?%) "%%")
                      ((eq character ?/) "%+")
                      ((eq character ?\\) "%-"))))
          (setq buffer-name (replace-match replacement t t buffer-name))
          (setq limit (1+ (match-end 0)))))
      ;; Generate the file name.
      (expand-file-name
       (format "#%s#%s#" buffer-name (make-temp-name ""))
       ;; Try a few alternative directories, to get one we can write it.
       (cond
        ((file-writable-p default-directory) default-directory)
        ((file-writable-p "/var/tmp/") "/var/tmp/")
        ("~/"))))))


> If your version of make-auto-save-file-name doesn't call
> convert-standard-file-name on any OS, perhaps you have an old Emacs
> (or else I have a too new Emacs ;-).

Oops, I wouldn't know how to run the same Emacs under Win. In any
case, while I do use Emacs both under Linux and Windows, they are
completely independent, and different major versions (gnu/linux:
21.2.1; windows-nt: 20.7.1).

I have had a look at how my Windows version does it ("*scratch*" will
become "#!scratch!#-16740779UIZ#"), and it appears that in w32-fns.el,
which is presumably loaded only under windows (I have just managed to
get the same behaviour by loading this library file under Linux, BTW,
though it hasn't loaded without error), make-auto-save-file-name is
renamed to 'original-make-auto-save-file-name and then redefined to

  (convert-standard-filename (original-make-auto-save-file-name))

convert-standard-filename is also defined to do something less
trivial; it converts all forbidden characters to "!", which is somehow
quite symbolic.


> > However, I've made a start. I've decided that no direct function
> > to the kernel to query mounted filesystems seems available, and
> > between looking at the output of /proc/mounts and calling mount with
> > no arguments, I've decided to do the latter (I don't know if any
> > approach is favourable over the other).
> 
> Why not call `df' instead?  I think "df ." should produce a line where
> one field gives you the type of the filesystem that you want.

df version 4.1 doesn't do so on my Debian woody, though it has an
option to exclude certain types of filesystems from being
considered. It sounds like it could be done on demand each time, if it
works. This would certainly be highly preferable, because nothing
could get out of date like that, and it would be less of a hassle to
program.

> > For looking up transforms, I'd like to have a list of alists of a
> > value and a list of alists each ;-) ... is that possible?
> 
> I'd try to use regexps and replace-match instead.

I have actually not yet made up my mind about the method of
transforming (I don't expect this to be problematic); what I want to
use the "list of alists of a value and a list of alists each" for is
to store rules on what type of fs what character to replace with what,
so read

  ("vfat" . (("*" . "_") ...

to mean "on a vfat fs, replace "*" with "_" (and so on)". I wanted to
make this user-customisable, hence the variable. Of course, come to
think of it, the car, i.e. "*" in this case, could just as well be a
regexp instead, i.e. "\\*" in this case, iirc.

> What doesn't work, exactly?

Oops, I tested it again, and, in fact, it works as expected. Probably
I simply messed up the cars and cdrs yesterday.

To sum up, I gather one would have to make changes similar to those in
w32-fns.el, up to the redefinition of make-auto-save-file-name, but
then define convert-standard-filename in the way you have suggested
(make it behave file system sensitive).

Would you agree, or do you think I have missed a point (does your
emacs version actually do it differently)?


And one call for help: could anyone please suggest a way of sorting
the list of alists I called "file-systems" demonstrated earlier in
this thread such that those alists whose car is the longer string come
first?

-- 


Florian v. Savigny

If you are going to reply in private, please be patient, as I only
check for mail something like once a week. - Si vous allez répondre
personellement, patientez s.v.p., car je ne lis les courriels
qu'environ une fois par semaine.

-- 


Florian v. Savigny

If you are going to reply in private, please be patient, as I only
check for mail something like once a week. - Si vous allez répondre
personellement, patientez s.v.p., car je ne lis les courriels
qu'environ une fois par semaine.


reply via email to

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