* lisp/emacs-lisp/lisp-mode.el (eval-defun-2): Simplify, using lexical-binding.
[bpt/emacs.git] / lisp / files.el
index 1be0304..ab62be2 100644 (file)
@@ -1,4 +1,4 @@
-;;; files.el --- file input and output commands for Emacs
+;;; files.el --- file input and output commands for Emacs  -*- lexical-binding:t -*-
 
 ;; Copyright (C) 1985-1987, 1992-2013 Free Software Foundation, Inc.
 
@@ -1603,13 +1603,16 @@ killed."
   "Create a suitably named buffer for visiting FILENAME, and return it.
 FILENAME (sans directory) is used unchanged if that name is free;
 otherwise a string <2> or <3> or ... is appended to get an unused name.
-Spaces at the start of FILENAME (sans directory) are removed."
+
+Emacs treats buffers whose names begin with a space as internal buffers.
+To avoid confusion when visiting a file whose name begins with a space,
+this function prepends a \"|\" to the final result if necessary."
   (let ((lastname (file-name-nondirectory filename)))
     (if (string= lastname "")
        (setq lastname filename))
-    (save-match-data
-      (string-match "^ *\\(.*\\)" lastname)
-      (generate-new-buffer (match-string 1 lastname)))))
+    (generate-new-buffer (if (string-match-p "\\` " lastname)
+                            (concat "|" lastname)
+                          lastname))))
 
 (defun generate-new-buffer (name)
   "Create and return a buffer with a name based on NAME.
@@ -2266,14 +2269,18 @@ since only a single case-insensitive search through the alist is made."
      ;; .PROCESSORNAME-gdbinit so that the host and target gdbinit files
      ;; don't interfere with each other.
      ("/\\.[a-z0-9-]*gdbinit" . gdb-script-mode)
+     ;; GDB 7.5 introduced OBJFILE-gdb.gdb script files; e.g. a file
+     ;; named 'emacs-gdb.gdb', if it exists, will be automatically
+     ;; loaded when GDB reads an objfile called 'emacs'.
+     ("-gdb\\.gdb" . gdb-script-mode)
      ("[cC]hange\\.?[lL]og?\\'" . change-log-mode)
      ("[cC]hange[lL]og[-.][0-9]+\\'" . change-log-mode)
      ("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode)
      ("\\.scm\\.[0-9]*\\'" . scheme-mode)
      ("\\.[ck]?sh\\'\\|\\.shar\\'\\|/\\.z?profile\\'" . sh-mode)
      ("\\.bash\\'" . sh-mode)
-     ("\\(/\\|\\`\\)\\.\\(bash_profile\\|z?login\\|bash_login\\|z?logout\\)\\'" . sh-mode)
-     ("\\(/\\|\\`\\)\\.\\(bash_logout\\|shrc\\|[kz]shrc\\|bashrc\\|t?cshrc\\|esrc\\)\\'" . sh-mode)
+     ("\\(/\\|\\`\\)\\.\\(bash_\\(profile\\|history\\|log\\(in\\|out\\)\\)\\|z?log\\(in\\|out\\)\\)\\'" . sh-mode)
+     ("\\(/\\|\\`\\)\\.\\(shrc\\|[kz]shrc\\|bashrc\\|t?cshrc\\|esrc\\)\\'" . sh-mode)
      ("\\(/\\|\\`\\)\\.\\([kz]shenv\\|xinitrc\\|startxrc\\|xsession\\)\\'" . sh-mode)
      ("\\.m?spec\\'" . sh-mode)
      ("\\.m[mes]\\'" . nroff-mode)
@@ -2444,34 +2451,21 @@ and `magic-mode-alist', which determines modes based on file contents.")
   (mapcar
    (lambda (l)
      (cons (purecopy (car l)) (cdr l)))
-   '(("perl" . perl-mode)
-     ("perl5" . perl-mode)
-     ("miniperl" . perl-mode)
-     ("wish" . tcl-mode)
-     ("wishx" . tcl-mode)
-     ("tcl" . tcl-mode)
-     ("tclsh" . tcl-mode)
+   '(("\\(mini\\)?perl5?" . perl-mode)
+     ("wishx?" . tcl-mode)
+     ("tcl\\(sh\\)?" . tcl-mode)
+     ("expect" . tcl-mode)
+     ("octave" . octave-mode)
      ("scm" . scheme-mode)
-     ("ash" . sh-mode)
-     ("bash" . sh-mode)
-     ("bash2" . sh-mode)
-     ("csh" . sh-mode)
-     ("dtksh" . sh-mode)
+     ("[acjkwz]sh" . sh-mode)
+     ("r?bash2?" . sh-mode)
+     ("\\(dt\\|pd\\|w\\)ksh" . sh-mode)
      ("es" . sh-mode)
-     ("itcsh" . sh-mode)
-     ("jsh" . sh-mode)
-     ("ksh" . sh-mode)
+     ("i?tcsh" . sh-mode)
      ("oash" . sh-mode)
-     ("pdksh" . sh-mode)
-     ("rbash" . sh-mode)
      ("rc" . sh-mode)
      ("rpm" . sh-mode)
-     ("sh" . sh-mode)
-     ("sh5" . sh-mode)
-     ("tcsh" . sh-mode)
-     ("wksh" . sh-mode)
-     ("wsh" . sh-mode)
-     ("zsh" . sh-mode)
+     ("sh5?" . sh-mode)
      ("tail" . text-mode)
      ("more" . text-mode)
      ("less" . text-mode)
@@ -2482,9 +2476,10 @@ and `magic-mode-alist', which determines modes based on file contents.")
      ("emacs" . emacs-lisp-mode)))
   "Alist mapping interpreter names to major modes.
 This is used for files whose first lines match `auto-mode-interpreter-regexp'.
-Each element looks like (INTERPRETER . MODE).
-If INTERPRETER matches the name of the interpreter specified in the first line
-of a script, mode MODE is enabled.
+Each element looks like (REGEXP . MODE).
+If \\\\`REGEXP\\\\' matches the name (minus any directory part) of
+the interpreter specified in the first line of a script, enable
+major mode MODE.
 
 See also `auto-mode-alist'.")
 
@@ -2679,19 +2674,23 @@ we don't actually set it to the same mode the buffer already has."
     ;; 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.
-    (unless done
-      (setq mode (save-excursion
-                  (goto-char (point-min))
-                  (if (looking-at auto-mode-interpreter-regexp)
-                      (match-string 2)
-                    ""))
-           ;; Map interpreter name to a mode, signaling 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)))
+    (and (not done)
+        (setq mode (save-excursion
+                     (goto-char (point-min))
+                     (if (looking-at auto-mode-interpreter-regexp)
+                         (match-string 2))))
+        ;; Map interpreter name to a mode, signaling we're done at the
+        ;; same time.
+        (setq done (assoc-default
+                    (file-name-nondirectory mode)
+                    (mapcar (lambda (e)
+                               (cons
+                                (format "\\`%s\\'" (car e))
+                                (cdr e)))
+                            interpreter-mode-alist)
+                    #'string-match-p))
+        ;; If we found an interpreter mode to use, invoke it now.
+        (set-auto-mode-0 done keep-mode-if-same))
     ;; Next try matching the buffer beginning against magic-mode-alist.
     (unless done
       (if (setq done (save-excursion
@@ -3643,22 +3642,17 @@ FILE is the name of the file holding the variables to apply.
 The new class name is the same as the directory in which FILE
 is found.  Returns the new class name."
   (with-temp-buffer
-    ;; This is with-demoted-errors, but we want to mention dir-locals
-    ;; in any error message.
-    (let (err)
-      (condition-case err
-         (progn
-           (insert-file-contents file)
-           (unless (zerop (buffer-size))
-             (let* ((dir-name (file-name-directory file))
-                    (class-name (intern dir-name))
-                    (variables (let ((read-circle nil))
-                                 (read (current-buffer)))))
-               (dir-locals-set-class-variables class-name variables)
-               (dir-locals-set-directory-class dir-name class-name
-                                               (nth 5 (file-attributes file)))
-               class-name)))
-       (error (message "Error reading dir-locals: %S" err) nil)))))
+    (with-demoted-errors "Error reading dir-locals: %S"
+      (insert-file-contents file)
+      (unless (zerop (buffer-size))
+        (let* ((dir-name (file-name-directory file))
+               (class-name (intern dir-name))
+               (variables (let ((read-circle nil))
+                            (read (current-buffer)))))
+          (dir-locals-set-class-variables class-name variables)
+          (dir-locals-set-directory-class dir-name class-name
+                                          (nth 5 (file-attributes file)))
+          class-name)))))
 
 (defcustom enable-remote-dir-locals nil
   "Non-nil means dir-local variables will be applied to remote files."
@@ -3666,6 +3660,8 @@ is found.  Returns the new class name."
   :type 'boolean
   :group 'find-file)
 
+(defvar hack-dir-local-variables--warned-coding nil)
+
 (defun hack-dir-local-variables ()
   "Read per-directory local variables for the current buffer.
 Store the directory-local variables in `dir-local-variables-alist'
@@ -3697,8 +3693,10 @@ This does nothing if either `enable-local-variables' or
          (when variables
            (dolist (elt variables)
              (if (eq (car elt) 'coding)
-                 (display-warning :warning
-                                  "Coding cannot be specified by dir-locals")
+                  (unless hack-dir-local-variables--warned-coding
+                    (setq hack-dir-local-variables--warned-coding t)
+                    (display-warning :warning
+                                     "Coding cannot be specified by dir-locals"))
                (unless (memq (car elt) '(eval mode))
                  (setq dir-local-variables-alist
                        (assq-delete-all (car elt) dir-local-variables-alist)))
@@ -4145,9 +4143,9 @@ FILENAME defaults to `buffer-file-name'."
   (file-name-sans-extension
    (file-name-nondirectory (or filename (buffer-file-name)))))
 
-(defcustom make-backup-file-name-function nil
+(defcustom make-backup-file-name-function
+  #'make-backup-file-name--default-function
   "A function to use instead of the default `make-backup-file-name'.
-A value of nil gives the default `make-backup-file-name' behavior.
 
 This could be buffer-local to do something special for specific
 files.  If you define it, you may need to change `backup-file-name-p'
@@ -4155,8 +4153,7 @@ and `file-name-sans-versions' too.
 
 See also `backup-directory-alist'."
   :group 'backup
-  :type '(choice (const :tag "Default" nil)
-                (function :tag "Your function")))
+  :type '(function :tag "Your function"))
 
 (defcustom backup-directory-alist nil
   "Alist of filename patterns and backup directory names.
@@ -4216,24 +4213,26 @@ Checks for files in `temporary-file-directory',
 Normally this will just be the file's name with `~' appended.
 Customization hooks are provided as follows.
 
-If the variable `make-backup-file-name-function' is non-nil, its value
-should be a function which will be called with FILE as its argument;
-the resulting name is used.
+The value of `make-backup-file-name-function' should be a function which
+will be called with FILE as its argument; the resulting name is used.
 
-Otherwise a match for FILE is sought in `backup-directory-alist'; see
+By default, a match for FILE is sought in `backup-directory-alist'; see
 the documentation of that variable.  If the directory for the backup
 doesn't exist, it is created."
-  (if make-backup-file-name-function
-      (funcall make-backup-file-name-function file)
-    (if (and (eq system-type 'ms-dos)
-            (not (msdos-long-file-names)))
-       (let ((fn (file-name-nondirectory file)))
-         (concat (file-name-directory file)
-                 (or (and (string-match "\\`[^.]+\\'" fn)
-                          (concat (match-string 0 fn) ".~"))
-                     (and (string-match "\\`[^.]+\\.\\(..?\\)?" fn)
-                          (concat (match-string 0 fn) "~")))))
-      (concat (make-backup-file-name-1 file) "~"))))
+  (funcall (or make-backup-file-name-function
+               #'make-backup-file-name--default-function)
+           file))
+
+(defun make-backup-file-name--default-function (file)
+  (if (and (eq system-type 'ms-dos)
+           (not (msdos-long-file-names)))
+      (let ((fn (file-name-nondirectory file)))
+        (concat (file-name-directory file)
+                (or (and (string-match "\\`[^.]+\\'" fn)
+                         (concat (match-string 0 fn) ".~"))
+                    (and (string-match "\\`[^.]+\\.\\(..?\\)?" fn)
+                         (concat (match-string 0 fn) "~")))))
+    (concat (make-backup-file-name-1 file) "~")))
 
 (defun make-backup-file-name-1 (file)
   "Subroutine of `make-backup-file-name' and `find-backup-file-name'."
@@ -5254,14 +5253,20 @@ It also has access to the `preserve-modes' argument of `revert-buffer'
 via the `revert-buffer-preserve-modes' dynamic variable.")
 
 (put 'revert-buffer-insert-file-contents-function 'permanent-local t)
-(defvar revert-buffer-insert-file-contents-function nil
+(defvar revert-buffer-insert-file-contents-function
+  #'revert-buffer-insert-file-contents--default-function
   "Function to use to insert contents when reverting this buffer.
 Gets two args, first the nominal file name to use,
 and second, t if reading the auto-save file.
 
 The function you specify is responsible for updating (or preserving) point.")
 
-(defvar buffer-stale-function nil
+(defun buffer-stale--default-function (&optional _noconfirm)
+  (and buffer-file-name
+       (file-readable-p buffer-file-name)
+       (not (verify-visited-file-modtime (current-buffer)))))
+
+(defvar buffer-stale-function #'buffer-stale--default-function
   "Function to check whether a non-file buffer needs reverting.
 This should be a function with one optional argument NOCONFIRM.
 Auto Revert Mode passes t for NOCONFIRM.  The function should return
@@ -5382,62 +5387,11 @@ non-nil, it is called instead of rereading visited file contents."
                    (local-hook (when (local-variable-p 'after-revert-hook)
                                  after-revert-hook))
                    (inhibit-read-only t))
-               (cond
-                (revert-buffer-insert-file-contents-function
-                 (unless (eq buffer-undo-list t)
-                   ;; Get rid of all undo records for this buffer.
-                   (setq buffer-undo-list nil))
-                 ;; Don't make undo records for the reversion.
-                 (let ((buffer-undo-list t))
-                   (funcall revert-buffer-insert-file-contents-function
-                            file-name auto-save-p)))
-                ((not (file-exists-p file-name))
-                 (error (if buffer-file-number
-                            "File %s no longer exists!"
-                          "Cannot revert nonexistent file %s")
-                        file-name))
-                ((not (file-readable-p file-name))
-                 (error (if buffer-file-number
-                            "File %s no longer readable!"
-                          "Cannot revert unreadable file %s")
-                        file-name))
-                (t
-                 ;; Bind buffer-file-name to nil
-                 ;; so that we don't try to lock the file.
-                 (let ((buffer-file-name nil))
-                   (or auto-save-p
-                       (unlock-buffer)))
-                 (widen)
-                 (let ((coding-system-for-read
-                        ;; Auto-saved file should be read by Emacs's
-                        ;; internal coding.
-                        (if auto-save-p 'auto-save-coding
-                          (or coding-system-for-read
-                              (and
-                               buffer-file-coding-system-explicit
-                               (car buffer-file-coding-system-explicit))))))
-                   (if (and (not enable-multibyte-characters)
-                            coding-system-for-read
-                            (not (memq (coding-system-base
-                                        coding-system-for-read)
-                                       '(no-conversion raw-text))))
-                       ;; As a coding system suitable for multibyte
-                       ;; buffer is specified, make the current
-                       ;; buffer multibyte.
-                       (set-buffer-multibyte t))
-
-                   ;; This force after-insert-file-set-coding
-                   ;; (called from insert-file-contents) to set
-                   ;; buffer-file-coding-system to a proper value.
-                   (kill-local-variable 'buffer-file-coding-system)
-
-                   ;; Note that this preserves point in an intelligent way.
-                   (if revert-buffer-preserve-modes
-                       (let ((buffer-file-format buffer-file-format))
-                         (insert-file-contents file-name (not auto-save-p)
-                                               nil nil t))
-                     (insert-file-contents file-name (not auto-save-p)
-                                           nil nil t)))))
+               ;; FIXME: Throw away undo-log when preserve-modes is nil?
+               (funcall
+                (or revert-buffer-insert-file-contents-function
+                    #'revert-buffer-insert-file-contents--default-function)
+                file-name auto-save-p)
                ;; Recompute the truename in case changes in symlinks
                ;; have changed the truename.
                (setq buffer-file-truename
@@ -5452,6 +5406,56 @@ non-nil, it is called instead of rereading visited file contents."
                (run-hooks 'revert-buffer-internal-hook))
              t)))))
 
+(defun revert-buffer-insert-file-contents--default-function (file-name auto-save-p)
+  (cond
+   ((not (file-exists-p file-name))
+    (error (if buffer-file-number
+               "File %s no longer exists!"
+             "Cannot revert nonexistent file %s")
+           file-name))
+   ((not (file-readable-p file-name))
+    (error (if buffer-file-number
+               "File %s no longer readable!"
+             "Cannot revert unreadable file %s")
+           file-name))
+   (t
+    ;; Bind buffer-file-name to nil
+    ;; so that we don't try to lock the file.
+    (let ((buffer-file-name nil))
+      (or auto-save-p
+          (unlock-buffer)))
+    (widen)
+    (let ((coding-system-for-read
+           ;; Auto-saved file should be read by Emacs's
+           ;; internal coding.
+           (if auto-save-p 'auto-save-coding
+             (or coding-system-for-read
+                 (and
+                  buffer-file-coding-system-explicit
+                  (car buffer-file-coding-system-explicit))))))
+      (if (and (not enable-multibyte-characters)
+               coding-system-for-read
+               (not (memq (coding-system-base
+                           coding-system-for-read)
+                          '(no-conversion raw-text))))
+          ;; As a coding system suitable for multibyte
+          ;; buffer is specified, make the current
+          ;; buffer multibyte.
+          (set-buffer-multibyte t))
+
+      ;; This force after-insert-file-set-coding
+      ;; (called from insert-file-contents) to set
+      ;; buffer-file-coding-system to a proper value.
+      (kill-local-variable 'buffer-file-coding-system)
+
+      ;; Note that this preserves point in an intelligent way.
+      (if revert-buffer-preserve-modes
+          (let ((buffer-file-format buffer-file-format))
+            (insert-file-contents file-name (not auto-save-p)
+                                  nil nil t))
+        (insert-file-contents file-name (not auto-save-p)
+                              nil nil t))))))
+
 (defun recover-this-file ()
   "Recover the visited file--get contents from its last auto-save file."
   (interactive)
@@ -6204,9 +6208,10 @@ normally equivalent short `-D' option is just passed on to
                    ;; directory if FILE is a symbolic link.
                    (unless full-directory-p
                      (setq switches
-                           (if (stringp switches)
-                               (concat switches " -d")
-                             (add-to-list 'switches "-d" 'append))))
+                           (cond
+                             ((stringp switches) (concat switches " -d"))
+                             ((member "-d" switches) switches)
+                             (t (append switches '("-d"))))))
                    (apply 'call-process
                           insert-directory-program nil t nil
                           (append
@@ -6680,7 +6685,9 @@ based on existing mode bits, as in \"og+rX-w\"."
          (string-to-number value 8)
        (file-modes-symbolic-to-number value modes)))))
 
-\f
+(define-obsolete-variable-alias 'cache-long-line-scans
+  'cache-long-scans "24.4")
+
 ;; Trashcan handling.
 (defcustom trash-directory nil
   "Directory for `move-file-to-trash' to move files and directories to.