]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
Merged in changes from CVS trunk.
[gnu-emacs] / lisp / files.el
index d14c4625352b1d765b49da461e9cb8c93f085566..62068b2f21798e66de737cd1f14a0b61b2a81960 100644 (file)
@@ -478,7 +478,7 @@ Runs the usual ange-ftp hook, but only for completion operations."
       (apply op args))))
 
 (defun convert-standard-filename (filename)
-  "Convert a standard file's name to something suitable for the current OS.
+  "Convert a standard file's name to something suitable for the OS.
 This means to guarantee valid names and perhaps to canonicalize
 certain patterns.
 
@@ -487,7 +487,9 @@ 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')."
+`w32-shell-dos-semantics').
+
+See Info node `(elisp)Standard File Names' for more details."
   filename)
 
 (defun read-directory-name (prompt &optional dir default-dirname mustmatch initial)
@@ -676,7 +678,7 @@ The truename of a file name is found by chasing symbolic links
 both at the level of the file and at the level of the directories
 containing it, until no links are left at any level.
 
-\(fn FILENAME)"
+\(fn FILENAME)"  ;; Don't document the optional arguments.
   ;; COUNTER and PREV-DIRS are only used in recursive calls.
   ;; COUNTER can be a cons cell whose car is the count of how many
   ;; more links to chase before getting an error.
@@ -977,6 +979,14 @@ expand wildcards (if any) and visit multiple files."
          (mapcar 'switch-to-buffer (cdr value)))
       (switch-to-buffer-other-frame value))))
 
+(defun find-file-existing (filename &optional wildcards)
+  "Edit the existing file FILENAME.
+Like \\[find-file] but only allow files that exists."
+  (interactive (find-file-read-args "Find existing file: " t))
+  (unless (file-exists-p filename) (error "%s does not exist" filename))
+  (find-file filename wildcards)
+  (current-buffer))
+
 (defun find-file-read-only (filename &optional wildcards)
   "Edit file FILENAME but don't allow changes.
 Like \\[find-file] but marks buffer as read-only.
@@ -1225,6 +1235,7 @@ suppresses this warning."
 When nil, never request confirmation."
   :group 'files
   :group 'find-file
+  :version "21.4"
   :type '(choice integer (const :tag "Never request confirmation" nil)))
 
 (defun find-file-noselect (filename &optional nowarn rawfile wildcards)
@@ -1645,7 +1656,9 @@ in that case, this function acts as if `enable-local-variables' were t."
   (mapc
    (lambda (elt)
      (cons (purecopy (car elt)) (cdr elt)))
-   '(("\\.te?xt\\'" . text-mode)
+   '(;; do this first, so that .html.pl is Polish html, not Perl
+     ("\\.s?html?\\(\\.[a-zA-Z_]+\\)?\\'" . html-mode)
+     ("\\.te?xt\\'" . text-mode)
      ("\\.[tT]e[xX]\\'" . tex-mode)
      ("\\.ins\\'" . tex-mode)          ;Installation files for TeX packages.
      ("\\.ltx\\'" . latex-mode)
@@ -1661,7 +1674,6 @@ in that case, this function acts as if `enable-local-variables' were t."
      ("\\.ad[abs]\\'" . ada-mode)
      ("\\.ad[bs].dg\\'" . ada-mode)
      ("\\.\\([pP]\\([Llm]\\|erl\\|od\\)\\|al\\)\\'" . perl-mode)
-     ("\\.s?html?\\'" . html-mode)
      ("\\.mk\\'" . makefile-mode)
      ("\\([Mm]\\|GNUm\\)akep*file\\'" . makefile-mode)
      ("\\.am\\'" . makefile-mode)      ;For Automake.
@@ -1689,7 +1701,8 @@ in that case, this function acts as if `enable-local-variables' were t."
      ("\\.bib\\'" . bibtex-mode)
      ("\\.sql\\'" . sql-mode)
      ("\\.m[4c]\\'" . m4-mode)
-     ("\\.m[fp]\\'" . metapost-mode)
+     ("\\.mf\\'" . metafont-mode)
+     ("\\.mp\\'" . metapost-mode)
      ("\\.vhdl?\\'" . vhdl-mode)
      ("\\.article\\'" . text-mode)
      ("\\.letter\\'" . text-mode)
@@ -1740,6 +1753,31 @@ in that case, this function acts as if `enable-local-variables' were t."
      ("BROWSE\\'" . ebrowse-tree-mode)
      ("\\.ebrowse\\'" . ebrowse-tree-mode)
      ("#\\*mail\\*" . mail-mode)
+     ("\\.g\\'" . antlr-mode)
+     ("\\.ses\\'" . ses-mode)
+     ("\\.\\(soa\\|zone\\)\\'" . dns-mode)
+     ("\\.docbook\\'" . sgml-mode)
+     ("/config\\.\\(?:bat\\|log\\)\\'" . fundamental-mode)
+     ;; Windows candidates may be opened case sensitively on Unix
+     ("\\.\\(?:[iI][nN][iI]\\|[lL][sS][tT]\\|[rR][eE][gG]\\|[sS][yY][sS]\\)\\'" . conf-mode)
+     ("\\.\\(?:desktop\\|la\\)\\'" . conf-unix-mode)
+     ("\\.ppd\\'" . conf-ppd-mode)
+     ("java.+\\.conf\\'" . conf-javaprop-mode)
+     ("\\.properties\\(?:\\.[a-zA-Z0-9._-]+\\)?\\'" . conf-javaprop-mode)
+     ;; *.cf, *.cfg, *.conf, *.config[.local|.de_DE.UTF8|...], */config
+     ("[/.]c\\(?:on\\)?f\\(?:i?g\\)?\\(?:\\.[a-zA-Z0-9._-]+\\)?\\'" . conf-mode)
+     ("\\`/etc/\\(?:DIR_COLORS\\|ethers\\|.?fstab\\|.*hosts\\|lesskey\\|login\\.?de\\(?:fs\\|vperm\\)\\|magic\\|mtab\\|pam\\.d/.*\\|permissions\\|protocols\\|rpc\\|services\\)\\'" . conf-space-mode)
+     ("\\`/etc/\\(?:acpid?/.+\\|aliases\\|default/.+\\|group-?\\|hosts\\..+\\|inittab\\|ksysguarddrc\\|opera6rc\\|passwd-?\\|shadow-?\\)\\'" . conf-mode)
+     ;; either user's dot-files or under /etc or some such
+     ("/\\.?\\(?:gnokiirc\\|kde.*rc\\|mime\\.types\\|wgetrc\\)\\'" . conf-mode)
+     ;; alas not all ~/.*rc files are like this
+     ("/\\.\\(?:enigma\\|gltron\\|gtk\\|hxplayer\\|net\\|neverball\\|qt/.+\\|realplayer\\|scummvm\\|sversion\\|sylpheed/.+\\|xmp\\)rc\\'" . conf-mode)
+     ("/\\.\\(?:gdbtkinit\\|grip\\|orbital/.+txt\\|rhosts\\|tuxracer/options\\)\\'" . conf-mode)
+     ("/\\.?X\\(?:default\\|resource\\|re\\)s\\>" . conf-xdefaults-mode)
+     ("/X11.+app-defaults/" . conf-xdefaults-mode)
+     ("/X11.+locale/.+/Compose\\'" . conf-colon-mode)
+     ;; this contains everything twice, with space and with colon :-(
+     ("/X11.+locale/compose\\.dir\\'" . conf-javaprop-mode)
      ;; Get rid of any trailing .n.m and try again.
      ;; This is for files saved by cvs-merge that look like .#<file>.<rev>
      ;; or .#<file>.<rev>-<rev> or VC's <file>.~<rev>~.
@@ -1750,11 +1788,7 @@ in that case, this function acts as if `enable-local-variables' were t."
      ;; for the sake of ChangeLog.1, etc.
      ;; and after the .scm.[0-9] and CVS' <file>.<rev> patterns too.
      ("\\.[1-9]\\'" . nroff-mode)
-     ("\\.g\\'" . antlr-mode)
-     ("\\.ses\\'" . ses-mode)
-     ("\\.orig\\'" nil t)              ; from patch
-     ("\\.\\(soa\\|zone\\)\\'" . dns-mode)
-     ("\\.in\\'" nil t)))
+     ("\\.\\(?:orig\\|in\\|[bB][aA][kK]\\)\\'" nil t)))
   "Alist of filename patterns vs corresponding major mode functions.
 Each element looks like (REGEXP . FUNCTION) or (REGEXP FUNCTION NON-NIL).
 \(NON-NIL stands for anything that is not nil; the value does not matter.)
@@ -1834,20 +1868,33 @@ be interpreted by the interpreter matched by the second group of the
 regular expression.  The mode is then determined as the mode associated
 with that interpreter in `interpreter-mode-alist'.")
 
-(defvar xml-based-modes '(html-mode)
-  "Modes that override an XML declaration.
-When `set-auto-mode' sees an <?xml or <!DOCTYPE declaration, that
-buffer will be in some XML mode.  If `auto-mode-alist' associates
-the file with one of the modes in this list, that mode will be
-used.  Else `xml-mode' or `sgml-mode' is used.")
-
-(defun set-auto-mode (&optional just-from-file-name)
+(defvar magic-mode-alist
+  `(;; The < comes before the groups (but the first) to reduce backtracking.
+    ;; TODO: UTF-16 <?xml may be preceded by a BOM 0xff 0xfe or 0xfe 0xff.
+    (,(let* ((incomment-re "\\(?:[^-]\\|-[^-]\\)")
+            (comment-re (concat "\\(?:!--" incomment-re "*-->\\s *<\\)")))
+       (concat "\\(?:<\\?xml\\s +[^>]*>\\)?\\s *<"
+               comment-re "*"
+               "\\(?:!DOCTYPE\\s +[^>]*>\\s *<\\s *" comment-re "*\\)?"
+               "[Hh][Tt][Mm][Ll]")) . html-mode)
+    ;; These two must come after html, because they are more general:
+    ("<\\?xml " . xml-mode)
+    (,(let* ((incomment-re "\\(?:[^-]\\|-[^-]\\)")
+            (comment-re (concat "\\(?:!--" incomment-re "*-->\\s *<\\)")))
+       (concat "\\s *<" comment-re "*!DOCTYPE ")) . sgml-mode)
+    ("%![^V]" . ps-mode)
+    ("# xmcd " . conf-unix-mode))
+  "Alist of buffer beginnings vs. corresponding major mode functions.
+Each element looks like (REGEXP . FUNCTION).  FUNCTION will be
+called, unless it is nil (to allow `auto-mode-alist' to override).")
+
+(defun set-auto-mode (&optional keep-mode-if-same)
   "Select major mode appropriate for current buffer.
+
 This checks for a -*- mode tag in the buffer's text, checks the
 interpreter that runs this file against `interpreter-mode-alist',
-looks for an <?xml or <!DOCTYPE declaration (see
-`xml-based-modes'), or compares the filename against the entries
-in `auto-mode-alist'.
+compares the buffer beginning against `magic-mode-alist', or
+compares the filename against the entries in `auto-mode-alist'.
 
 It does not check for the `mode:' local variable in the
 Local Variables section of the file; for that, use `hack-local-variables'.
@@ -1855,89 +1902,104 @@ Local Variables section of the file; for that, use `hack-local-variables'.
 If `enable-local-variables' is nil, this function does not check for a
 -*- mode tag.
 
-If the optional argument JUST-FROM-FILE-NAME is non-nil,
-then we do not set anything but the major mode,
-and we don't even do that unless it would come from the file name."
+If the optional argument KEEP-MODE-IF-SAME is non-nil, then we
+only set the major mode, if that would change it."
   ;; Look for -*-MODENAME-*- or -*- ... mode: MODENAME; ... -*-
-  (let (end done mode modes xml)
-    (unless just-from-file-name
-      ;; Find a -*- mode tag
-      (save-excursion
-       (goto-char (point-min))
-       (skip-chars-forward " \t\n")
-       ;; While we're at this point, check xml for later.
-       (setq xml (looking-at "<\\?xml \\|<!DOCTYPE"))
-       (and enable-local-variables
-            (setq end (set-auto-mode-1))
-            (if (save-excursion (search-forward ":" end t))
-                ;; Find all specifications for the `mode:' variable
-                ;; and execute them left to right.
-                (while (let ((case-fold-search t))
-                         (or (and (looking-at "mode:")
-                                  (goto-char (match-end 0)))
-                             (re-search-forward "[ \t;]mode:" end t)))
-                  (skip-chars-forward " \t")
-                  (let ((beg (point)))
-                    (if (search-forward ";" end t)
-                        (forward-char -1)
-                      (goto-char end))
-                    (skip-chars-backward " \t")
-                    (push (intern (concat (downcase (buffer-substring beg (point))) "-mode"))
-                          modes)))
-              ;; Simple -*-MODE-*- case.
-              (push (intern (concat (downcase (buffer-substring (point) end))
-                                    "-mode"))
-                    modes))))
-      ;; If we found modes to use, invoke them now, outside the save-excursion.
-      (if modes
+  (let (end done mode modes)
+    ;; Find a -*- mode tag
+    (save-excursion
+      (goto-char (point-min))
+      (skip-chars-forward " \t\n")
+      (and enable-local-variables
+          (setq end (set-auto-mode-1))
+          (if (save-excursion (search-forward ":" end t))
+              ;; Find all specifications for the `mode:' variable
+              ;; and execute them left to right.
+              (while (let ((case-fold-search t))
+                       (or (and (looking-at "mode:")
+                                (goto-char (match-end 0)))
+                           (re-search-forward "[ \t;]mode:" end t)))
+                (skip-chars-forward " \t")
+                (let ((beg (point)))
+                  (if (search-forward ";" end t)
+                      (forward-char -1)
+                    (goto-char end))
+                  (skip-chars-backward " \t")
+                  (push (intern (concat (downcase (buffer-substring beg (point))) "-mode"))
+                        modes)))
+            ;; Simple -*-MODE-*- case.
+            (push (intern (concat (downcase (buffer-substring (point) end))
+                                  "-mode"))
+                  modes))))
+    ;; If we found modes to use, invoke them now, outside the save-excursion.
+    (if modes
+       (catch 'nop
          (dolist (mode (nreverse modes))
            (if (not (functionp mode))
                (message "Ignoring unknown mode `%s'" mode)
              (setq done t)
-             (funcall mode)))
-       ;; If we didn't, look for an interpreter specified in the first line.
-       ;; As a special case, allow for things like "#!/bin/env perl", which
-       ;; finds the interpreter anywhere in $PATH.
-       (setq mode (save-excursion
-                    (goto-char (point-min))
-                    (if (looking-at auto-mode-interpreter-regexp)
-                        (match-string 2)
-                      ""))
-             ;; Map interpreter name to a mode, signalling we're done at the
-             ;; same time.
-             done (assoc (file-name-nondirectory mode)
-                         interpreter-mode-alist))
-       ;; If we found an interpreter mode to use, invoke it now.
-       (if done (funcall (cdr done)))))
-    (if (and (not done) buffer-file-name)
-       (let ((name buffer-file-name))
-         ;; Remove backup-suffixes from file name.
-         (setq name (file-name-sans-versions name))
-         (while (not done)
-           ;; Find first matching alist entry.
-           (let ((case-fold-search
-                  (memq system-type '(vax-vms windows-nt cygwin))))
-             (if (and (setq mode (assoc-default name auto-mode-alist
-                                                'string-match))
-                      (consp mode)
-                      (cadr mode))
-                 (setq mode (car mode)
-                       name (substring name 0 (match-beginning 0)))
-               (setq done t)))
-           (if mode
-               ;; When JUST-FROM-FILE-NAME is set, we are working on behalf
-               ;; of set-visited-file-name.  In that case, if the major mode
-               ;; specified is the same one we already have, don't actually
-               ;; reset it.  We don't want to lose minor modes such as Font
-               ;; Lock.
-               (unless (and just-from-file-name (eq mode major-mode))
-                 (if (if xml (memq mode xml-based-modes) t)
-                     (funcall mode)
-                   (xml-mode)))))))
-    (and (not done)
-        xml
-        (xml-mode))))
-
+             (or (set-auto-mode-0 mode keep-mode-if-same)
+                 ;; continuing would call minor modes again, toggling them off
+                 (throw 'nop nil)))))
+      ;; If we didn't, look for an interpreter specified in the first line.
+      ;; As a special case, allow for things like "#!/bin/env perl", which
+      ;; finds the interpreter anywhere in $PATH.
+      (setq mode (save-excursion
+                  (goto-char (point-min))
+                  (if (looking-at auto-mode-interpreter-regexp)
+                      (match-string 2)
+                    ""))
+           ;; Map interpreter name to a mode, signalling we're done at the
+           ;; same time.
+           done (assoc (file-name-nondirectory mode)
+                       interpreter-mode-alist))
+      ;; If we found an interpreter mode to use, invoke it now.
+      (if done
+         (set-auto-mode-0 (cdr done) keep-mode-if-same)))
+    ;; If we didn't, match the buffer beginning against magic-mode-alist.
+    (unless done
+      (if (setq done (save-excursion
+                      (goto-char (point-min))
+                      (assoc-default nil magic-mode-alist
+                                     (lambda (re dummy)
+                                       (looking-at re)))))
+         (set-auto-mode-0 done keep-mode-if-same)
+       ;; Compare the filename against the entries in auto-mode-alist.
+       (if buffer-file-name
+           (let ((name buffer-file-name))
+             ;; Remove backup-suffixes from file name.
+             (setq name (file-name-sans-versions name))
+             (while name
+               ;; Find first matching alist entry.
+               (let ((case-fold-search
+                      (memq system-type '(vax-vms windows-nt cygwin))))
+                 (if (and (setq mode (assoc-default name auto-mode-alist
+                                                    'string-match))
+                          (consp mode)
+                          (cadr mode))
+                     (setq mode (car mode)
+                           name (substring name 0 (match-beginning 0)))
+                   (setq name)))
+               (when mode
+                 (set-auto-mode-0 mode keep-mode-if-same)))))))))
+
+;; When `keep-mode-if-same' is set, we are working on behalf of
+;; set-visited-file-name.  In that case, if the major mode specified is the
+;; same one we already have, don't actually reset it.  We don't want to lose
+;; minor modes such as Font Lock.
+(defun set-auto-mode-0 (mode &optional keep-mode-if-same)
+  "Apply MODE and return it.
+If optional arg KEEP-MODE-IF-SAME is non-nil, MODE is chased of
+any aliases and compared to current major mode.  If they are the
+same, do nothing and return nil."
+  (when keep-mode-if-same
+    (while (symbolp (symbol-function mode))
+      (setq mode (symbol-function mode)))
+    (if (eq mode major-mode)
+       (setq mode nil)))
+  (when mode
+    (funcall mode)
+    mode))
 
 (defun set-auto-mode-1 ()
   "Find the -*- spec in the buffer.
@@ -3797,7 +3859,7 @@ This command is used in the special Dired buffer created by
 
 (defun kill-some-buffers (&optional list)
   "Kill some buffers.  Asks the user whether to kill each one of them.
-Non-interactively, if optional argument LIST is non-`nil', it
+Non-interactively, if optional argument LIST is non-nil, it
 specifies the list of buffers to kill, asking for approval for each one."
   (interactive)
   (if (null list)
@@ -4578,7 +4640,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)