]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
(recover-file): Fix error message.
[gnu-emacs] / lisp / files.el
index 1341cd909b2d092b89be798f49b48809a6b8325b..15f9c3af56470b8e724b3691a7eb6f9aad666b31 100644 (file)
@@ -489,70 +489,90 @@ unlike `file-truename'."
       (setq count (1- count)))
     newname))
 \f
-(defun switch-to-buffer-other-window (buffer)
-  "Select buffer BUFFER in another window."
+(defun switch-to-buffer-other-window (buffer &optional norecord)
+  "Select buffer BUFFER in another window.
+Optional second arg NORECORD non-nil means
+do not put this buffer at the front of the list of recently selected ones."
   (interactive "BSwitch to buffer in other window: ")
   (let ((pop-up-windows t))
-    (pop-to-buffer buffer t)))
+    (pop-to-buffer buffer t norecord)))
 
-(defun switch-to-buffer-other-frame (buffer)
-  "Switch to buffer BUFFER in another frame."
+(defun switch-to-buffer-other-frame (buffer &optional norecord)
+  "Switch to buffer BUFFER in another frame.
+Optional second arg NORECORD non-nil means
+do not put this buffer at the front of the list of recently selected ones."
   (interactive "BSwitch to buffer in other frame: ")
   (let ((pop-up-frames t))
-    (pop-to-buffer buffer t)
+    (pop-to-buffer buffer t norecord)
     (raise-frame (window-frame (selected-window)))))
 
-(defun find-file (filename)
+(defun find-file (filename &optional coding-system)
   "Edit file FILENAME.
 Switch to a buffer visiting file FILENAME,
-creating one if none already exists."
-  (interactive "FFind file: ")
-  (switch-to-buffer (find-file-noselect filename)))
-
-(defun find-file-other-window (filename)
+creating one if none already exists.
+A prefix argument enables user to specify the coding-system interactively."
+  (interactive "FFind file: \nZCoding-system: ")
+  (if coding-system
+      (let ((coding-system-for-read coding-system))
+       (switch-to-buffer (find-file-noselect filename)))
+    (switch-to-buffer (find-file-noselect filename))))
+
+(defun find-file-other-window (filename &optional coding-system)
   "Edit file FILENAME, in another window.
 May create a new window, or reuse an existing one.
+A prefix argument enables user to specify the coding-system interactively.
 See the function `display-buffer'."
-  (interactive "FFind file in other window: ")
-  (switch-to-buffer-other-window (find-file-noselect filename)))
+  (interactive "FFind file in other window: \nZCoding-system: ")
+  (if coding-system
+      (let ((coding-system-for-read coding-system))
+       (switch-to-buffer-other-window (find-file-noselect filename)))
+    (switch-to-buffer-other-window (find-file-noselect filename))))
 
-(defun find-file-other-frame (filename)
+(defun find-file-other-frame (filename &optional coding-system)
   "Edit file FILENAME, in another frame.
 May create a new frame, or reuse an existing one.
+A prefix argument enables user to specify the coding-system interactively.
 See the function `display-buffer'."
-  (interactive "FFind file in other frame: ")
-  (switch-to-buffer-other-frame (find-file-noselect filename)))
+  (interactive "FFind file in other frame: \nZCoding-system: ")
+  (if coding-system
+      (let ((coding-system-for-read coding-system))
+       (switch-to-buffer-other-frame (find-file-noselect filename)))
+    (switch-to-buffer-other-frame (find-file-noselect filename))))
 
-(defun find-file-read-only (filename)
+(defun find-file-read-only (filename &optional coding-system)
   "Edit file FILENAME but don't allow changes.
 Like \\[find-file] but marks buffer as read-only.
+A prefix argument enables user to specify the coding-system interactively.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only: ")
-  (find-file filename)
+  (interactive "fFind file read-only: \nZCoding-system: ")
+  (find-file filename coding-system)
   (setq buffer-read-only t)
   (current-buffer))
 
-(defun find-file-read-only-other-window (filename)
+(defun find-file-read-only-other-window (filename &optional coding-system)
   "Edit file FILENAME in another window but don't allow changes.
 Like \\[find-file-other-window] but marks buffer as read-only.
+A prefix argument enables user to specify the coding-system interactively.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only other window: ")
-  (find-file-other-window filename)
+  (interactive "fFind file read-only other window: \nZCoding-system: ")
+  (find-file-other-window filename coding-system)
   (setq buffer-read-only t)
   (current-buffer))
 
-(defun find-file-read-only-other-frame (filename)
+(defun find-file-read-only-other-frame (filename &optional coding-system)
   "Edit file FILENAME in another frame but don't allow changes.
 Like \\[find-file-other-frame] but marks buffer as read-only.
+A prefix argument enables user to specify the coding-system interactively.
 Use \\[toggle-read-only] to permit editing."
-  (interactive "fFind file read-only other frame: ")
-  (find-file-other-frame filename)
+  (interactive "fFind file read-only other frame: \nZCoding-system: ")
+  (find-file-other-frame filename coding-system)
   (setq buffer-read-only t)
   (current-buffer))
 
-(defun find-alternate-file-other-window (filename)
+(defun find-alternate-file-other-window (filename &optional coding-system)
   "Find file FILENAME as a replacement for the file in the next window.
-This command does not select that window."
+This command does not select that window.
+A prefix argument enables user to specify the coding-system interactively."
   (interactive
    (save-selected-window
      (other-window 1)
@@ -563,17 +583,20 @@ This command does not select that window."
            (setq file-name (file-name-nondirectory file)
                  file-dir (file-name-directory file)))
        (list (read-file-name
-             "Find alternate file: " file-dir nil nil file-name)))))
+             "Find alternate file: " file-dir nil nil file-name)
+            (if current-prefix-arg
+                (read-coding-system "Coding-system: "))))))
   (if (one-window-p)
-      (find-file-other-window filename)
+      (find-file-other-window filename coding-system)
     (save-selected-window
       (other-window 1)
-      (find-alternate-file filename))))
+      (find-alternate-file filename coding-system))))
 
-(defun find-alternate-file (filename)
+(defun find-alternate-file (filename &optional coding-system)
   "Find file FILENAME, select its buffer, kill previous buffer.
 If the current buffer now contains an empty file that you just visited
-\(presumably by mistake), use this command to visit the file you really want."
+\(presumably by mistake), use this command to visit the file you really want.
+A prefix argument enables user to specify the coding-system interactively."
   (interactive
    (let ((file buffer-file-name)
         (file-name nil)
@@ -582,7 +605,9 @@ If the current buffer now contains an empty file that you just visited
          (setq file-name (file-name-nondirectory file)
                file-dir (file-name-directory file)))
      (list (read-file-name
-           "Find alternate file: " file-dir nil nil file-name))))
+           "Find alternate file: " file-dir nil nil file-name)
+          (if current-prefix-arg
+              (read-coding-system "Coding-system: ")))))
   (and (buffer-modified-p) (buffer-file-name)
        ;; (not buffer-read-only)
        (not (yes-or-no-p (format "Buffer %s is modified; kill anyway? "
@@ -602,7 +627,7 @@ If the current buffer now contains an empty file that you just visited
          (setq buffer-file-name nil)
          (setq buffer-file-number nil)
          (setq buffer-file-truename nil)
-         (find-file filename))
+         (find-file filename coding-system))
       (cond ((eq obuf (current-buffer))
             (setq buffer-file-name ofile)
             (setq buffer-file-number onum)
@@ -749,7 +774,9 @@ file name handlers and remote file access uses a file name handler."
   "Read file FILENAME into a buffer and return the buffer.
 If a buffer exists visiting FILENAME, return that one, but
 verify that the file has not changed since visited or saved.
-The buffer is not selected, just returned to the caller."
+The buffer is not selected, just returned to the caller.
+Optional first arg NOWARN non-nil means suppress any warning messages.
+Optional second arg RAWFILE non-nil means the file is read literally"
   (setq filename
        (abbreviate-file-name
         (expand-file-name filename)))
@@ -1036,6 +1063,7 @@ run `normal-mode' explicitly."
     ("\\.oak\\'" . scheme-mode)
     ("\\.sgml?\\'" . sgml-mode)
     ("\\.dtd\\'" . sgml-mode)
+    ("\\.ds\\(ss\\)?l\\'" . dsssl-mode)
     ("\\.s?html?\\'" . html-mode)
     ;; .emacs following a directory delimiter
     ;; in either Unix or VMS syntax.
@@ -1453,7 +1481,7 @@ in order to initialize other data structure based on them.")
           (set var val))))
 
 \f
-(defun set-visited-file-name (filename &optional no-query)
+(defun set-visited-file-name (filename &optional no-query along-with-file)
   "Change name of file visited in current buffer to FILENAME.
 The next time the buffer is saved it will go in the newly specified file.
 nil or empty string as argument means make buffer not be visiting any file.
@@ -1461,7 +1489,10 @@ Remember to delete the initial contents of the minibuffer
 if you wish to pass an empty string as the argument.
 
 The optional second argument NO-QUERY, if non-nil, inhibits asking for
-confirmation in the case where another buffer is already visiting FILENAME."
+confirmation in the case where another buffer is already visiting FILENAME.
+
+The optional third argument ALONG-WITH-FILE, if non-nil, means that
+the old visited file has been renamed to the new name FILENAME."
   (interactive "FSet visited file name: ")
   (if (buffer-base-buffer)
       (error "An indirect buffer cannot visit a file"))
@@ -1497,7 +1528,8 @@ confirmation in the case where another buffer is already visiting FILENAME."
          (or (string= new-name (buffer-name))
              (rename-buffer new-name t))))
     (setq buffer-backed-up nil)
-    (clear-visited-file-modtime)
+    (or along-with-file
+       (clear-visited-file-modtime))
     ;; Abbreviate the file names of the buffer.
     (if truename
        (progn
@@ -1542,10 +1574,11 @@ confirmation in the case where another buffer is already visiting FILENAME."
     (and oauto buffer-auto-save-file-name
         (file-exists-p oauto)
         (rename-file oauto buffer-auto-save-file-name t)))
-  (if buffer-file-name
-      (set-buffer-modified-p t)))
+  (and buffer-file-name
+       (not along-with-file)
+       (set-buffer-modified-p t)))
 
-(defun write-file (filename &optional confirm)
+(defun write-file (filename &optional confirm coding-system)
   "Write current buffer into file FILENAME.
 Makes buffer visit that file, and marks it not modified.
 If the buffer is already visiting a file, you can specify
@@ -1554,7 +1587,10 @@ old name in that directory.
 
 If optional second arg CONFIRM is non-nil,
 ask for confirmation for overwriting an existing file.
-Interactively, confirmation is required unless you supply a prefix argument."
+Interactively, confirmation is required unless you supply a prefix argument.
+
+A prefix argument also enables user to interactively specify a
+coding-system for encoding the file."
 ;;  (interactive "FWrite file: ")
   (interactive
    (list (if buffer-file-name
@@ -1564,7 +1600,10 @@ Interactively, confirmation is required unless you supply a prefix argument."
                               (cdr (assq 'default-directory
                                          (buffer-local-variables)))
                               nil nil (buffer-name)))
-        (not current-prefix-arg)))
+        (not current-prefix-arg)
+        (if current-prefix-arg
+            (read-coding-system "Coding-system: "))
+        ))
   (or (null filename) (string-equal filename "")
       (progn
        ;; If arg is just a directory,
@@ -1578,7 +1617,13 @@ Interactively, confirmation is required unless you supply a prefix argument."
                 (error "Canceled")))
        (set-visited-file-name filename (not confirm))))
   (set-buffer-modified-p t)
-  (save-buffer))
+  (if coding-system
+      (let ((coding-system-for-write coding-system))
+       ;; It is convenient to change buffer-file-coding-system to the
+       ;; specified one.
+       (set-buffer-file-coding-system coding-system)
+       (save-buffer))
+    (save-buffer)))
 \f
 (defun backup-buffer ()
   "Make a backup of the disk file visited by the current buffer, if appropriate.
@@ -1820,15 +1865,28 @@ If the value is nil, don't make a backup."
   (car (cdr (file-attributes filename))))
 
 (defun file-relative-name (filename &optional directory)
-  "Convert FILENAME to be relative to DIRECTORY (default: default-directory)."
-  (setq filename (expand-file-name filename)
-       directory (file-name-as-directory (expand-file-name
-                                          (or directory default-directory))))
-  (let ((ancestor ""))
-    (while (not (string-match (concat "^" (regexp-quote directory)) filename))
-      (setq directory (file-name-directory (substring directory 0 -1))
-           ancestor (concat "../" ancestor)))
-    (concat ancestor (substring filename (match-end 0)))))
+  "Convert FILENAME to be relative to DIRECTORY (default: default-directory).
+This function returns a relative file name which is equivalent to FILENAME
+when used with that default directory as the default.
+If this is impossible (which can happen on MSDOS and Windows
+when the file name and directory use different drive names)
+then it returns FILENAME."
+  (save-match-data
+    (setq fname (expand-file-name filename)
+         directory (file-name-as-directory
+                    (expand-file-name (or directory default-directory))))
+    ;; On Microsoft OSes, if FILENAME and DIRECTORY have different
+    ;; drive names, they can't be relative, so return the absolute name.
+    (if (and (or (eq system-type 'ms-dos)
+                (eq system-type 'windows-nt))
+            (not (string-equal (substring fname  0 2)
+                               (substring directory 0 2))))
+       filename
+      (let ((ancestor ""))
+       (while (not (string-match (concat "^" (regexp-quote directory)) fname))
+         (setq directory (file-name-directory (substring directory 0 -1))
+               ancestor (concat "../" ancestor)))
+       (concat ancestor (substring fname (match-end 0)))))))
 \f
 (defun save-buffer (&optional args)
   "Save current buffer in visited file if modified.  Versions described below.
@@ -2106,27 +2164,36 @@ With arg, set read-only iff arg is positive."
             (> (prefix-numeric-value arg) 0)))
   (force-mode-line-update))
 
-(defun insert-file (filename)
+(defun insert-file (filename &optional coding-system)
   "Insert contents of file FILENAME into buffer after point.
 Set mark after the inserted text.
+A prefix argument enables user to specify the coding-system interactively.
 
 This function is meant for the user to run interactively.
 Don't call it from programs!  Use `insert-file-contents' instead.
 \(Its calling sequence is different; see its documentation)."
-  (interactive "*fInsert file: ")
+  (interactive "*fInsert file: \nZCoding-system: ")
   (if (file-directory-p filename)
       (signal 'file-error (list "Opening input file" "file is a directory"
                                filename)))
-  (let ((tem (insert-file-contents filename)))
+  (let ((tem
+        (if coding-system
+            (let ((coding-system-for-read coding-system))
+              (insert-file-contents filename))
+          (insert-file-contents filename))))
     (push-mark (+ (point) (car (cdr tem))))))
 
-(defun append-to-file (start end filename)
+(defun append-to-file (start end filename &optional coding-system)
   "Append the contents of the region to the end of file FILENAME.
 When called from a function, expects three arguments,
 START, END and FILENAME.  START and END are buffer positions
-saying what text to write."
-  (interactive "r\nFAppend to file: ")
-  (write-region start end filename t))
+saying what text to write.
+A prefix argument enables user to specify the coding-system interactively."
+  (interactive "r\nFAppend to file: \nZCoding-system: ")
+  (if coding-system
+      (let ((coding-system-for-write coding-system))
+       (write-region start end filename t))
+    (write-region start end filename t)))
 
 (defun file-newest-backup (filename)
   "Return most recent backup file for FILENAME or nil if no backups exist."
@@ -2345,11 +2412,13 @@ non-nil, it is called instead of rereading visited file contents."
                                 file file-name)))
             (yes-or-no-p (format "Recover auto save file %s? " file-name)))
           (switch-to-buffer (find-file-noselect file t))
-          (let ((buffer-read-only nil))
+          (let ((buffer-read-only nil)
+                ;; Auto-saved file shoule be read without any code conversion.
+                (coding-system-for-read 'no-conversion))
             (erase-buffer)
             (insert-file-contents file-name nil))
           (after-find-file nil nil t))
-         (t (error "Recover-file cancelled.")))))
+         (t (error "Recover-file cancelled")))))
 
 (defun recover-session ()
   "Recover auto save files from a previous Emacs session.
@@ -2361,7 +2430,8 @@ Then you'll be asked about a number of files to recover."
   (if (null auto-save-list-file-prefix)
       (error "You set `auto-save-list-file-prefix' to disable making session files"))
   (let ((ls-lisp-support-shell-wildcards t))
-    (dired (concat auto-save-list-file-prefix "*")))
+    (dired (concat auto-save-list-file-prefix "*")
+          (concat dired-listing-switches "t")))
   (goto-char (point-min))
   (or (looking-at "Move to the session you want to recover,")
       (let ((inhibit-read-only t))
@@ -2521,20 +2591,17 @@ See also `auto-save-file-name-p'."
 
     (let ((buffer-name (buffer-name))
          (limit 0))
-      ;; Use technique from Sebastian Kremer's auto-save
-      ;; package to turn slashes into \\!.  This ensures that
-      ;; the auto-save buffer name is unique.
-
-      (while (string-match "[/\\]" buffer-name limit)
-       (setq buffer-name (concat (substring buffer-name 0 (match-beginning 0))
-                       (if (string= (substring buffer-name
-                                               (match-beginning 0)
-                                               (match-end 0))
-                                    "/")
-                           "\\!"
-                         "\\\\")
-                       (substring buffer-name (match-end 0))))
-       (setq limit (1+ (match-end 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 ""))
@@ -2726,7 +2793,7 @@ If WILDCARD, it also runs the shell specified by `shell-file-name'."
                                                (if (stringp switches)
                                                    switches
                                                  (mapconcat 'identity switches " "))
-                                               " "
+                                               " -- "
                                                pattern)))
                 ;; SunOS 4.1.3, SVr4 and others need the "." to list the
                 ;; directory if FILE is a symbolic link.
@@ -2745,6 +2812,8 @@ If WILDCARD, it also runs the shell specified by `shell-file-name'."
                                          switches (substring switches (match-end 0))))
                                  (setq list (nreverse (cons switches list))))))
                          (append list
+                                 ;; Avoid lossage if FILE starts with `-'.
+                                 '("--")
                                  (list
                                   (if full-directory-p
                                       (concat (file-name-as-directory file) ".")