Merged in changes from CVS trunk.
[bpt/emacs.git] / lisp / files.el
index 99cad16..138cced 100644 (file)
@@ -393,7 +393,8 @@ updates before the buffer is saved, use `before-save-hook' .")
 (defvar write-contents-functions nil
   "List of functions to be called before writing out a buffer to a file.
 If one of them returns non-nil, the file is considered already written
-and the rest are not called.
+and the rest are not called and neither are the functions in
+`write-file-functions'.
 
 This variable is meant to be used for hooks that pertain to the
 buffer's contents, not to the particular visited file; thus,
@@ -481,10 +482,15 @@ Runs the usual ange-ftp hook, but only for completion operations."
 
 (defun convert-standard-filename (filename)
   "Convert a standard file's name to something suitable for the current OS.
-This function's standard definition is trivial; it just returns the argument.
-However, on some systems, the function is redefined with a definition
-that really does change some file names to canonicalize certain
-patterns and to guarantee valid names."
+This means to guarantee valid names and perhaps to canonicalize
+certain patterns.
+
+This function's standard definition is trivial; it just returns
+the argument.  However, on Windows and DOS, replace invalid
+characters.  On DOS, make sure to obey the 8.3 limitations.  On
+Windows, turn Cygwin names into native names, and also turn
+slashes into backslashes if the shell requires it (see
+`w32-shell-dos-semantics')."
   filename)
 
 (defun read-directory-name (prompt &optional dir default-dirname mustmatch initial)
@@ -521,8 +527,9 @@ the value of `default-directory'."
 Not actually set up until the first time you use it.")
 
 (defun parse-colon-path (cd-path)
-  "Explode a colon-separated search path into a list of directory names.
-\(For values of `colon' equal to `path-separator'.)"
+  "Explode a search path into a list of directory names.
+Directories are separated by occurrences of `path-separator'
+\(which is colon in GNU and GNU-like systems)."
   ;; We could use split-string here.
   (and cd-path
        (let (cd-list (cd-start 0) cd-colon)
@@ -555,8 +562,10 @@ Not actually set up until the first time you use it.")
 
 (defun cd (dir)
   "Make DIR become the current buffer's default directory.
-If your environment includes a `CDPATH' variable, try each one of that
-colon-separated list of directories when resolving a relative directory name."
+If your environment includes a `CDPATH' variable, try each one of
+that list of directories (separated by occurrences of
+`path-separator') when resolving a relative directory name.
+The path separator is colon in GNU and GNU-like systems."
   (interactive
    (list (read-directory-name "Change default directory: "
                         default-directory default-directory
@@ -641,10 +650,17 @@ This is an interface to the function `load'."
   (load library))
 
 (defun file-remote-p (file)
-  "Test whether FILE specifies a location on a remote system."
-  (let ((handler (find-file-name-handler file 'file-local-copy)))
+  "Test whether FILE specifies a location on a remote system.
+Return an identification of the system if the location is indeed
+remote.  The identification of the system may comprise a method
+to access the system and its hostname, amongst other things.
+
+For example, the filename \"/user@host:/foo\" specifies a location
+on the system \"/user@host:\"."
+  (let ((handler (find-file-name-handler file 'file-remote-p)))
     (if handler
-       (get handler 'file-remote-p))))
+       (funcall handler 'file-remote-p file)
+      nil)))
 
 (defun file-local-copy (file)
   "Copy the file FILE into a temporary file on this machine.
@@ -853,8 +869,15 @@ use with M-x."
 \f
 (defun switch-to-buffer-other-window (buffer &optional norecord)
   "Select buffer BUFFER in another window.
+If BUFFER does not identify an existing buffer, then this function
+creates a buffer with that name.
+
+When called from Lisp, BUFFER can be a buffer, a string \(a buffer name),
+or nil.  If BUFFER is nil, then this function chooses a buffer
+using `other-buffer'.
 Optional second arg NORECORD non-nil means
 do not put this buffer at the front of the list of recently selected ones.
+This function returns the buffer it switched to.
 
 This uses the function `display-buffer' as a subroutine; see its
 documentation for additional customization information."
@@ -905,8 +928,11 @@ but the visited file name is available through the minibuffer history:
 type M-n to pull it into the minibuffer.
 
 Interactively, or if WILDCARDS is non-nil in a call from Lisp,
-expand wildcards (if any) and visit multiple files.  Wildcard expansion
-can be suppressed by setting `find-file-wildcards'."
+expand wildcards (if any) and visit multiple files.  You can
+suppress wildcard expansion by setting `find-file-wildcards'.
+
+To visit a file without any kind of conversion and without
+automatically choosing a major mode, use \\[find-file-literally]."
   (interactive
    (find-file-read-args "Find file: " nil))
   (let ((value (find-file-noselect filename nil nil wildcards)))
@@ -1357,21 +1383,22 @@ that are visiting the various files."
                                rawfile truename number))))))
 
 (defun find-file-noselect-1 (buf filename nowarn rawfile truename number)
-  (let ((inhibit-read-only t)
-       error)
+  (let (error)
     (with-current-buffer buf
       (kill-local-variable 'find-file-literally)
       ;; Needed in case we are re-visiting the file with a different
       ;; text representation.
       (kill-local-variable 'buffer-file-coding-system)
       (kill-local-variable 'cursor-type)
-      (erase-buffer)
+      (let ((inhibit-read-only t))
+       (erase-buffer))
       (and (default-value 'enable-multibyte-characters)
           (not rawfile)
           (set-buffer-multibyte t))
       (if rawfile
          (condition-case ()
-             (insert-file-contents-literally filename t)
+             (let ((inhibit-read-only t))
+               (insert-file-contents-literally filename t))
            (file-error
             (when (and (file-exists-p filename)
                        (not (file-readable-p filename)))
@@ -1381,7 +1408,8 @@ that are visiting the various files."
             ;; Unconditionally set error
             (setq error t)))
        (condition-case ()
-           (insert-file-contents filename t)
+           (let ((inhibit-read-only t))
+             (insert-file-contents filename t))
          (file-error
           (when (and (file-exists-p filename)
                      (not (file-readable-p filename)))
@@ -1743,6 +1771,7 @@ in that case, this function acts as if `enable-local-variables' were t."
      ("\\.g\\'" . antlr-mode)
      ("\\.ses\\'" . ses-mode)
      ("\\.orig\\'" nil t)              ; from patch
+     ("\\.\\(soa\\|zone\\)\\'" . dns-mode)
      ("\\.in\\'" nil t)))
   "Alist of filename patterns vs corresponding major mode functions.
 Each element looks like (REGEXP . FUNCTION) or (REGEXP FUNCTION NON-NIL).
@@ -2901,10 +2930,8 @@ on a DOS/Windows machine, it returns FILENAME on expanded form."
          (file-name-as-directory (expand-file-name (or directory
                                                        default-directory))))
     (setq filename (expand-file-name filename))
-    (let ((hf (find-file-name-handler filename 'file-local-copy))
-          (hd (find-file-name-handler directory 'file-local-copy)))
-      (when (and hf (not (get hf 'file-remote-p))) (setq hf nil))
-      (when (and hd (not (get hd 'file-remote-p))) (setq hd nil))
+    (let ((fremote (file-remote-p filename))
+          (dremote (file-remote-p directory)))
       (if ;; Conditions for separate trees
          (or
           ;; Test for different drives on DOS/Windows
@@ -2912,20 +2939,8 @@ on a DOS/Windows machine, it returns FILENAME on expanded form."
            ;; Should `cygwin' really be included here?  --stef
            (memq system-type '(ms-dos cygwin windows-nt))
            (not (eq t (compare-strings filename 0 2 directory 0 2))))
-          ;; Test for different remote file handlers
-          (not (eq hf hd))
           ;; Test for different remote file system identification
-          (and
-           hf
-           (let ((re (car (rassq hf file-name-handler-alist))))
-             (not
-              (equal
-               (and
-                (string-match re filename)
-                (substring filename 0 (match-end 0)))
-               (and
-                (string-match re directory)
-                (substring directory 0 (match-end 0))))))))
+          (not (equal fremote dremote)))
          filename
         (let ((ancestor ".")
              (filename-dir (file-name-as-directory filename)))
@@ -3014,7 +3029,7 @@ the last real save, but optional arg FORCE non-nil means delete anyway."
 
 (defcustom before-save-hook nil
   "Normal hook that is run before a buffer is saved to its file."
-  :options '(copyright-update)
+  :options '(copyright-update time-stamp)
   :type 'hook
   :group 'files)
 
@@ -3470,7 +3485,10 @@ this function is called.
 The idea behind the NOCONFIRM argument is that it should be
 non-nil if the buffer is going to be reverted without asking the
 user.  In such situations, one has to be careful with potentially
-time consuming operations.")
+time consuming operations.
+
+For more information on how this variable is used by Auto Revert mode,
+see Info node `(emacs-xtra)Supporting additional buffers'.")
 
 (defvar before-revert-hook nil
   "Normal hook for `revert-buffer' to run before reverting.
@@ -4335,21 +4353,26 @@ normally equivalent short `-D' option is just passed on to
             (when (looking-at "//SUBDIRED//")
               (delete-region (point) (progn (forward-line 1) (point)))
               (forward-line -1))
-           (let ((end (line-end-position)))
-             (forward-word 1)
-             (forward-char 3)
-             (while (< (point) end)
-               (let ((start (+ beg (read (current-buffer))))
-                     (end (+ beg (read (current-buffer)))))
-                 (if (= (char-after end) ?\n)
-                     (put-text-property start end 'dired-filename t)
-                   ;; It seems that we can't trust ls's output as to
-                   ;; byte positions of filenames.
-                   (put-text-property beg (point) 'dired-filename nil)
-                   (end-of-line))))
-             (goto-char end)
-             (beginning-of-line)
-             (delete-region (point) (progn (forward-line 2) (point)))))
+           (if (looking-at "//DIRED//")
+               (let ((end (line-end-position)))
+                 (forward-word 1)
+                 (forward-char 3)
+                 (while (< (point) end)
+                   (let ((start (+ beg (read (current-buffer))))
+                         (end (+ beg (read (current-buffer)))))
+                     (if (= (char-after end) ?\n)
+                         (put-text-property start end 'dired-filename t)
+                       ;; It seems that we can't trust ls's output as to
+                       ;; byte positions of filenames.
+                       (put-text-property beg (point) 'dired-filename nil)
+                       (end-of-line))))
+                 (goto-char end)
+                 (beginning-of-line)
+                 (delete-region (point) (progn (forward-line 2) (point))))
+             (forward-line 1)
+             (if (looking-at "//DIRED-OPTIONS//")
+                 (delete-region (point) (progn (forward-line 1) (point)))
+               (forward-line 1))))
 
          ;; Now decode what read if necessary.
          (let ((coding (or coding-system-for-read
@@ -4476,7 +4499,7 @@ With prefix arg, silently save all file-visiting buffers, then kill."
        ;; Get a list of the indices of the args which are file names.
        (file-arg-indices
         (cdr (or (assq operation
-                       ;; The first five are special because they
+                       ;; The first six are special because they
                        ;; return a file name.  We want to include the /:
                        ;; in the return value.
                        ;; So just avoid stripping it in the first place.
@@ -4485,11 +4508,21 @@ With prefix arg, silently save all file-visiting buffers, then kill."
                          (file-name-as-directory . nil)
                          (directory-file-name . nil)
                          (file-name-sans-versions . nil)
+                         (find-backup-file-name . nil)
                          ;; `identity' means just return the first arg
-                         ;; as stripped of its quoting.
-                         (substitute-in-file-name . identity)
+                         ;; not stripped of its quoting.
+                         (substitute-in-file-name identity)
+                         ;; `add' means add "/:" to the result.
+                         (file-truename add 0)
+                         ;; `quote' means add "/:" to buffer-file-name.
+                         (insert-file-contents quote 0)
+                         ;; `unquote-then-quote' means set buffer-file-name
+                         ;; temporarily to unquoted filename.
+                         (verify-visited-file-modtime unquote-then-quote)
+                         ;; List the arguments which are filenames.
                          (file-name-completion 1)
                          (file-name-all-completions 1)
+                         (write-region 2 5)
                          (rename-file 0 1)
                          (copy-file 0 1)
                          (make-symbolic-link 0 1)
@@ -4497,9 +4530,12 @@ With prefix arg, silently save all file-visiting buffers, then kill."
                  ;; For all other operations, treat the first argument only
                  ;; as the file name.
                  '(nil 0))))
+       method
        ;; Copy ARGUMENTS so we can replace elements in it.
        (arguments (copy-sequence arguments)))
-    ;; Strip off the /: from the file names that have this handler.
+    (if (symbolp (car file-arg-indices))
+       (setq method (pop file-arg-indices)))
+    ;; Strip off the /: from the file names that have it.
     (save-match-data
       (while (consp file-arg-indices)
        (let ((pair (nthcdr (car file-arg-indices) arguments)))
@@ -4510,9 +4546,21 @@ With prefix arg, silently save all file-visiting buffers, then kill."
                           "/"
                         (substring (car pair) 2)))))
        (setq file-arg-indices (cdr file-arg-indices))))
-    (if (eq file-arg-indices 'identity)
-       (car arguments)
-      (apply operation arguments))))
+    (cond ((eq method 'identity)
+          (car arguments))
+         ((eq method 'add)
+          (concat "/:" (apply operation arguments)))
+         ((eq method 'quote)
+          (prog1 (apply operation arguments)
+            (setq buffer-file-name (concat "/:" buffer-file-name))))
+         ((eq method 'unquote-then-quote)
+          (let (res)
+            (setq buffer-file-name (substring buffer-file-name 2))
+            (setq res (apply operation arguments))
+            (setq buffer-file-name (concat "/:" buffer-file-name))
+            res))
+         (t
+          (apply operation arguments)))))
 \f
 (define-key ctl-x-map "\C-f" 'find-file)
 (define-key ctl-x-map "\C-r" 'find-file-read-only)
@@ -4523,7 +4571,7 @@ With prefix arg, silently save all file-visiting buffers, then kill."
 (define-key ctl-x-map "i" 'insert-file)
 (define-key esc-map "~" 'not-modified)
 (define-key ctl-x-map "\C-d" 'list-directory)
-(define-key ctl-x-map "\C-c" 'save-buffers-kill-emacs)
+(define-key ctl-x-map "\C-c" 'server-save-buffers-kill-display)
 (define-key ctl-x-map "\C-q" 'toggle-read-only)
 
 (define-key ctl-x-4-map "f" 'find-file-other-window)