]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
Merge from emacs-23.
[gnu-emacs] / lisp / files.el
index ee77975e38b5d9a333d07c0110897fa6e9e6950f..dcb9ac08d9540c2adf75dd2e4bb551d05daa20ac 100644 (file)
@@ -5,6 +5,7 @@
 ;;   2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
+;; Package: emacs
 
 ;; This file is part of GNU Emacs.
 
@@ -117,13 +118,14 @@ This variable is relevant only if `backup-by-copying' is nil."
   :type 'boolean
   :group 'backup)
 
-(defcustom backup-by-copying-when-mismatch nil
+(defcustom backup-by-copying-when-mismatch t
   "Non-nil means create backups by copying if this preserves owner or group.
 Renaming may still be used (subject to control of other variables)
 when it would not result in changing the owner or group of the file;
 that is, for files which are owned by you and whose group matches
 the default for a new file created there by you.
 This variable is relevant only if `backup-by-copying' is nil."
+  :version "24.1"
   :type 'boolean
   :group 'backup)
 (put 'backup-by-copying-when-mismatch 'permanent-local t)
@@ -191,17 +193,6 @@ If the buffer is visiting a new file, the value is nil.")
   "Non-nil if visited file was read-only when visited.")
 (make-variable-buffer-local 'buffer-file-read-only)
 
-(defcustom temporary-file-directory
-  (file-name-as-directory
-   (cond ((memq system-type '(ms-dos windows-nt))
-         (or (getenv "TEMP") (getenv "TMPDIR") (getenv "TMP") "c:/temp"))
-        (t
-         (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "/tmp"))))
-  "The directory for writing temporary files."
-  :group 'files
-  :initialize 'custom-initialize-delay
-  :type 'directory)
-
 (defcustom small-temporary-file-directory
   (if (eq system-type 'ms-dos) (getenv "TMPDIR"))
   "The directory for writing small temporary files.
@@ -578,6 +569,9 @@ Runs the usual ange-ftp hook, but only for completion operations."
          (inhibit-file-name-operation op))
       (apply op args))))
 
+(declare-function dos-convert-standard-filename "dos-fns.el" (filename))
+(declare-function w32-convert-standard-filename "w32-fns.el" (filename))
+
 (defun convert-standard-filename (filename)
   "Convert a standard file's name to something suitable for the OS.
 This means to guarantee valid names and perhaps to canonicalize
@@ -595,15 +589,20 @@ and also turn slashes into backslashes if the shell requires it (see
 `w32-shell-dos-semantics').
 
 See Info node `(elisp)Standard File Names' for more details."
-  (if (eq system-type 'cygwin)
-      (let ((name (copy-sequence filename))
-           (start 0))
-       ;; Replace invalid filename characters with !
-       (while (string-match "[?*:<>|\"\000-\037]" name start)
-              (aset name (match-beginning 0) ?!)
-         (setq start (match-end 0)))
-       name)
-    filename))
+  (cond
+   ((eq system-type 'cygwin)
+    (let ((name (copy-sequence filename))
+         (start 0))
+      ;; Replace invalid filename characters with !
+      (while (string-match "[?*:<>|\"\000-\037]" name start)
+       (aset name (match-beginning 0) ?!)
+       (setq start (match-end 0)))
+      name))
+   ((eq system-type 'windows-nt)
+    (w32-convert-standard-filename filename))
+   ((eq system-type 'ms-dos)
+    (dos-convert-standard-filename filename))
+   (t filename)))
 
 (defun read-directory-name (prompt &optional dir default-dirname mustmatch initial)
   "Read directory name, prompting with PROMPT and completing in directory DIR.
@@ -753,21 +752,45 @@ one or more of those symbols."
              (let ((x (file-name-directory suffix)))
                (if x (1- (length x)) (length suffix))))))
    (t
-    (let ((names nil)
+    (let ((names '())
+          ;; If we have files like "foo.el" and "foo.elc", we could load one of
+          ;; them with "foo.el", "foo.elc", or "foo", where just "foo" is the
+          ;; preferred way.  So if we list all 3, that gives a lot of redundant
+          ;; entries for the poor soul looking just for "foo".  OTOH, sometimes
+          ;; the user does want to pay attention to the extension.  We try to
+          ;; diffuse this tension by stripping the suffix, except when the
+          ;; result is a single element (i.e. usually we only list "foo" unless
+          ;; it's the only remaining element in the list, in which case we do
+          ;; list "foo", "foo.elc" and "foo.el").
+          (fullnames '())
          (suffix (concat (regexp-opt suffixes t) "\\'"))
          (string-dir (file-name-directory string))
           (string-file (file-name-nondirectory string)))
       (dolist (dir dirs)
-       (unless dir
-         (setq dir default-directory))
-       (if string-dir (setq dir (expand-file-name string-dir dir)))
-       (when (file-directory-p dir)
-         (dolist (file (file-name-all-completions
-                        string-file dir))
-           (push file names)
-           (when (string-match suffix file)
-             (setq file (substring file 0 (match-beginning 0)))
-              (push file names)))))
+        (unless dir
+          (setq dir default-directory))
+        (if string-dir (setq dir (expand-file-name string-dir dir)))
+        (when (file-directory-p dir)
+          (dolist (file (file-name-all-completions
+                         string-file dir))
+            (if (not (string-match suffix file))
+                (push file names)
+              (push file fullnames)
+              (push (substring file 0 (match-beginning 0)) names)))))
+      ;; Switching from names to names+fullnames creates a non-monotonicity
+      ;; which can cause problems with things like partial-completion.
+      ;; To minimize the problem, filter out completion-regexp-list, so that
+      ;; M-x load-library RET t/x.e TAB finds some files.  Also remove elements
+      ;; from `names' which only matched `string' when they still had
+      ;; their suffix.
+      (setq names (all-completions string names))
+      ;; Remove duplicates of the first element, so that we can easily check
+      ;; if `names' really only contains a single element.
+      (when (cdr names) (setcdr names (delete (car names) (cdr names))))
+      (unless (cdr names)
+        ;; There's no more than one matching non-suffixed element, so expand
+        ;; the list by adding the suffixed elements as well.
+        (setq names (nconc names fullnames)))
       (completion-table-with-context
        string-dir names string-file pred action)))))
 
@@ -906,6 +929,36 @@ to that remote system.
        (funcall handler 'file-remote-p file identification connected)
       nil)))
 
+(defcustom remote-file-name-inhibit-cache 10
+  "Whether to use the remote file-name cache for read access.
+
+When `nil', always use the cached values.
+When `t', never use them.
+A number means use them for that amount of seconds since they were
+cached.
+
+File attributes of remote files are cached for better performance.
+If they are changed out of Emacs' control, the cached values
+become invalid, and must be invalidated.
+
+In case a remote file is checked regularly, it might be
+reasonable to let-bind this variable to a value less then the
+time period between two checks.
+Example:
+
+  \(defun display-time-file-nonempty-p \(file)
+    \(let \(\(remote-file-name-inhibit-cache \(- display-time-interval 5)))
+      \(and \(file-exists-p file)
+           \(< 0 \(nth 7 \(file-attributes \(file-chase-links file)))))))"
+  :group 'files
+  :version "24.1"
+  :type `(choice
+         (const   :tag "Do not inhibit file name cache" nil)
+         (const   :tag "Do not use file name cache" t)
+         (integer :tag "Do not use file name cache"
+                  :format "Do not use file name cache older then %v seconds"
+                  :value 10)))
+
 (defun file-local-copy (file)
   "Copy the file FILE into a temporary file on this machine.
 Returns the name of the local copy, or nil, if FILE is directly
@@ -1506,7 +1559,7 @@ killed."
     (error "Aborted"))
   (when (and (buffer-modified-p) buffer-file-name)
     (if (yes-or-no-p (format "Buffer %s is modified; save it first? "
-                             (buffer-name)))
+                            (buffer-name)))
         (save-buffer)
       (unless (yes-or-no-p "Kill and replace the buffer without saving it? ")
         (error "Aborted"))))
@@ -1708,12 +1761,11 @@ When nil, never request confirmation."
   "If file SIZE larger than `large-file-warning-threshold', allow user to abort.
 OP-TYPE specifies the file operation being performed (for message to user)."
   (when (and large-file-warning-threshold size
-          (> size large-file-warning-threshold)
-          (not (y-or-n-p
-                (format "File %s is large (%dMB), really %s? "
-                        (file-name-nondirectory filename)
-                        (/ size 1048576) op-type))))
-         (error "Aborted")))
+            (> size large-file-warning-threshold)
+            (not (y-or-n-p (format "File %s is large (%dMB), really %s? "
+                                   (file-name-nondirectory filename)
+                                   (/ size 1048576) op-type))))
+    (error "Aborted")))
 
 (defun find-file-noselect (filename &optional nowarn rawfile wildcards)
   "Read file FILENAME into a buffer and return the buffer.
@@ -2163,7 +2215,7 @@ in that case, this function acts as if `enable-local-variables' were t."
   (if (fboundp 'ucs-set-table-for-input) ; don't lose when building
       (ucs-set-table-for-input)))
 
-(defcustom auto-mode-case-fold nil
+(defcustom auto-mode-case-fold t
   "Non-nil means to try second pass through `auto-mode-alist'.
 This means that if the first case-sensitive search through the alist fails
 to find a matching major mode, a second case-insensitive search is made.
@@ -2182,7 +2234,16 @@ since only a single case-insensitive search through the alist is made."
    (lambda (elt)
      (cons (purecopy (car elt)) (cdr elt)))
    `(;; do this first, so that .html.pl is Polish html, not Perl
-     ("\\.s?html?\\(\\.[a-zA-Z_]+\\)?\\'" . html-mode)
+     ("\\.[sx]?html?\\(\\.[a-zA-Z_]+\\)?\\'" . html-mode)
+     ("\\.svgz?\\'" . image-mode)
+     ("\\.svgz?\\'" . xml-mode)
+     ("\\.x[bp]m\\'" . image-mode)
+     ("\\.x[bp]m\\'" . c-mode)
+     ("\\.p[bpgn]m\\'" . image-mode)
+     ("\\.tiff?\\'" . image-mode)
+     ("\\.gif\\'" . image-mode)
+     ("\\.png\\'" . image-mode)
+     ("\\.jpe?g\\'" . image-mode)
      ("\\.te?xt\\'" . text-mode)
      ("\\.[tT]e[xX]\\'" . tex-mode)
      ("\\.ins\\'" . tex-mode)          ;Installation files for TeX packages.
@@ -2218,6 +2279,14 @@ since only a single case-insensitive search through the alist is made."
      ("\\.te?xi\\'" . texinfo-mode)
      ("\\.[sS]\\'" . asm-mode)
      ("\\.asm\\'" . asm-mode)
+     ("\\.css\\'" . css-mode)
+     ("\\.mixal\\'" . mixal-mode)
+     ("\\.gcov\\'" . compilation-mode)
+     ;; Besides .gdbinit, gdb documents other names to be usable for init
+     ;; files, cross-debuggers can use something like
+     ;; .PROCESSORNAME-gdbinit so that the host and target gdbinit files
+     ;; don't interfere with each other.
+     ("/\\.[a-z0-9-]*gdbinit" . 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)
@@ -2234,6 +2303,7 @@ since only a single case-insensitive search through the alist is made."
      ("\\.cl[so]\\'" . latex-mode)             ;LaTeX 2e class option
      ("\\.bbl\\'" . latex-mode)
      ("\\.bib\\'" . bibtex-mode)
+     ("\\.bst\\'" . bibtex-style-mode)
      ("\\.sql\\'" . sql-mode)
      ("\\.m[4c]\\'" . m4-mode)
      ("\\.mf\\'" . metafont-mode)
@@ -2256,15 +2326,14 @@ since only a single case-insensitive search through the alist is made."
      ;; The list of archive file extensions should be in sync with
      ;; `auto-coding-alist' with `no-conversion' coding system.
      ("\\.\\(\
-arc\\|zip\\|lzh\\|lha\\|zoo\\|[jew]ar\\|xpi\\|rar\\|\
-ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\)\\'" . archive-mode)
+arc\\|zip\\|lzh\\|lha\\|zoo\\|[jew]ar\\|xpi\\|rar\\|7z\\|\
+ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|7Z\\)\\'" . archive-mode)
      ("\\.\\(sx[dmicw]\\|od[fgpst]\\|oxt\\)\\'" . archive-mode) ;OpenOffice.org
      ("\\.\\(deb\\|[oi]pk\\)\\'" . archive-mode) ; Debian/Opkg packages.
      ;; Mailer puts message to be edited in
      ;; /tmp/Re.... or Message
      ("\\`/tmp/Re" . text-mode)
      ("/Message[0-9]*\\'" . text-mode)
-     ("\\.zone\\'" . zone-mode)
      ;; some news reader is reported to use this
      ("\\`/tmp/fol/" . text-mode)
      ("\\.oak\\'" . scheme-mode)
@@ -2284,6 +2353,20 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\)\\'" . archive-mode)
      ("[:/]_emacs\\'" . emacs-lisp-mode)
      ("/crontab\\.X*[0-9]+\\'" . shell-script-mode)
      ("\\.ml\\'" . lisp-mode)
+     ;; Linux-2.6.9 uses some different suffix for linker scripts:
+     ;; "ld", "lds", "lds.S", "lds.in", "ld.script", and "ld.script.balo".
+     ;; eCos uses "ld" and "ldi".  Netbsd uses "ldscript.*".
+     ("\\.ld[si]?\\'" . ld-script-mode)
+     ("ld\\.?script\\'" . ld-script-mode)
+     ;; .xs is also used for ld scripts, but seems to be more commonly
+     ;; associated with Perl .xs files (C with Perl bindings).  (Bug#7071)
+     ("\\.xs\\'" . c-mode)
+     ;; Explained in binutils ld/genscripts.sh.  Eg:
+     ;; A .x script file is the default script.
+     ;; A .xr script is for linking without relocation (-r flag).  Etc.
+     ("\\.x[abdsru]?[cnw]?\\'" . ld-script-mode)
+     ("\\.zone\\'" . dns-mode)
+     ("\\.soa\\'" . dns-mode)
      ;; Common Lisp ASDF package system.
      ("\\.asd\\'" . lisp-mode)
      ("\\.\\(asn\\|mib\\|smi\\)\\'" . snmp-mode)
@@ -2291,7 +2374,7 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\)\\'" . archive-mode)
      ("\\.\\(diffs?\\|patch\\|rej\\)\\'" . diff-mode)
      ("\\.\\(dif\\|pat\\)\\'" . diff-mode) ; for MSDOG
      ("\\.[eE]?[pP][sS]\\'" . ps-mode)
-     ("\\.\\(?:PDF\\|DVI\\|pdf\\|dvi\\)\\'" . doc-view-mode)
+     ("\\.\\(?:PDF\\|DVI\\|OD[FGPST]\\|DOCX?\\|XLSX?\\|PPTX?\\|pdf\\|dvi\\|od[fgpst]\\|docx?\\|xlsx?\\|pptx?\\)\\'" . doc-view-mode-maybe)
      ("configure\\.\\(ac\\|in\\)\\'" . autoconf-mode)
      ("\\.s\\(v\\|iv\\|ieve\\)\\'" . sieve-mode)
      ("BROWSE\\'" . ebrowse-tree-mode)
@@ -2299,7 +2382,6 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\)\\'" . archive-mode)
      ("#\\*mail\\*" . mail-mode)
      ("\\.g\\'" . antlr-mode)
      ("\\.ses\\'" . ses-mode)
-     ("\\.\\(soa\\|zone\\)\\'" . dns-mode)
      ("\\.docbook\\'" . sgml-mode)
      ("\\.com\\'" . dcl-mode)
      ("/config\\.\\(?:bat\\|log\\)\\'" . fundamental-mode)
@@ -2409,7 +2491,8 @@ and `magic-mode-alist', which determines modes based on file contents.")
      ("pg" . text-mode)
      ("make" . makefile-gmake-mode)            ; Debian uses this
      ("guile" . scheme-mode)
-     ("clisp" . lisp-mode)))
+     ("clisp" . lisp-mode)
+     ("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).
@@ -2772,15 +2855,19 @@ asking you for confirmation."
 
 (mapc (lambda (pair)
        (put (car pair) 'safe-local-variable (cdr pair)))
-      '((buffer-read-only     . booleanp)   ;; C source code
-       (default-directory    . stringp)    ;; C source code
-       (fill-column          . integerp)   ;; C source code
-       (indent-tabs-mode     . booleanp)   ;; C source code
-       (left-margin          . integerp)   ;; C source code
-       (no-update-autoloads  . booleanp)
-       (tab-width            . integerp)   ;; C source code
-       (truncate-lines       . booleanp)   ;; C source code
-       (word-wrap            . booleanp))) ;; C source code
+      '((buffer-read-only        . booleanp)   ;; C source code
+       (default-directory       . stringp)    ;; C source code
+       (fill-column             . integerp)   ;; C source code
+       (indent-tabs-mode        . booleanp)   ;; C source code
+       (left-margin             . integerp)   ;; C source code
+       (no-update-autoloads     . booleanp)
+       (tab-width               . integerp)   ;; C source code
+       (truncate-lines          . booleanp)   ;; C source code
+       (word-wrap               . booleanp) ;; C source code
+       (bidi-display-reordering . booleanp))) ;; C source code
+
+(put 'bidi-paragraph-direction 'safe-local-variable
+     (lambda (v) (memq v '(nil right-to-left left-to-right))))
 
 (put 'c-set-style 'safe-local-eval-function t)
 
@@ -2821,91 +2908,80 @@ DIR-NAME is a directory name if these settings come from
 directory-local variables, or nil otherwise."
   (if noninteractive
       nil
-    (let ((name (or dir-name
-                   (if buffer-file-name
-                       (file-name-nondirectory buffer-file-name)
-                     (concat "buffer " (buffer-name)))))
-         (offer-save (and (eq enable-local-variables t) unsafe-vars))
-         prompt char)
-      (save-window-excursion
-       (let ((buf (get-buffer-create "*Local Variables*")))
-         (pop-to-buffer buf)
-         (set (make-local-variable 'cursor-type) nil)
-         (erase-buffer)
-         (if unsafe-vars
-             (insert "The local variables list in " name
-                     "\ncontains values that may not be safe (*)"
-                     (if risky-vars
-                         ", and variables that are risky (**)."
-                       "."))
-           (if risky-vars
-               (insert "The local variables list in " name
-                       "\ncontains variables that are risky (**).")
-             (insert "A local variables list is specified in " name ".")))
-         (insert "\n\nDo you want to apply it?  You can type
+    (save-window-excursion
+      (let* ((name (or dir-name
+                      (if buffer-file-name
+                          (file-name-nondirectory buffer-file-name)
+                        (concat "buffer " (buffer-name)))))
+            (offer-save (and (eq enable-local-variables t)
+                             unsafe-vars))
+            (exit-chars
+             (if offer-save '(?! ?y ?n ?\s ?\C-g) '(?y ?n ?\s ?\C-g)))
+            (buf (pop-to-buffer "*Local Variables*"))
+            prompt char)
+       (set (make-local-variable 'cursor-type) nil)
+       (erase-buffer)
+       (cond
+        (unsafe-vars
+         (insert "The local variables list in " name
+                 "\ncontains values that may not be safe (*)"
+                 (if risky-vars
+                     ", and variables that are risky (**)."
+                   ".")))
+        (risky-vars
+         (insert "The local variables list in " name
+                 "\ncontains variables that are risky (**)."))
+        (t
+         (insert "A local variables list is specified in " name ".")))
+       (insert "\n\nDo you want to apply it?  You can type
 y  -- to apply the local variables list.
 n  -- to ignore the local variables list.")
-         (if offer-save
-             (insert "
+       (if offer-save
+           (insert "
 !  -- to apply the local variables list, and permanently mark these
       values (*) as safe (in the future, they will be set automatically.)\n\n")
-           (insert "\n\n"))
-         (dolist (elt all-vars)
-           (cond ((member elt unsafe-vars)
-                  (insert "  * "))
-                 ((member elt risky-vars)
-                  (insert " ** "))
-                 (t
-                  (insert "    ")))
-           (princ (car elt) buf)
-           (insert " : ")
-            ;; Make strings with embedded whitespace easier to read.
-            (let ((print-escape-newlines t))
-              (prin1 (cdr elt) buf))
-           (insert "\n"))
-         (setq prompt
-               (format "Please type %s%s: "
-                       (if offer-save "y, n, or !" "y or n")
-                       (if (< (line-number-at-pos) (window-body-height))
-                           ""
-                         ", or C-v to scroll")))
-         (goto-char (point-min))
-         (let ((cursor-in-echo-area t)
-               (executing-kbd-macro executing-kbd-macro)
-               (exit-chars
-                (if offer-save '(?! ?y ?n ?\s ?\C-g) '(?y ?n ?\s ?\C-g)))
-               done)
-           (while (not done)
-             (message "%s" prompt)
-             (setq char (read-event))
-             (if (numberp char)
-                 (cond ((eq char ?\C-v)
-                        (condition-case nil
-                            (scroll-up)
-                          (error (goto-char (point-min)))))
-                       ;; read-event returns -1 if we are in a kbd
-                       ;; macro and there are no more events in the
-                       ;; macro.  In that case, attempt to get an
-                       ;; event interactively.
-                       ((and executing-kbd-macro (= char -1))
-                        (setq executing-kbd-macro nil))
-                       (t (setq done (memq (downcase char) exit-chars)))))))
-         (setq char (downcase char))
-         (when (and offer-save (= char ?!) unsafe-vars)
-           (dolist (elt unsafe-vars)
-             (add-to-list 'safe-local-variable-values elt))
-           ;; When this is called from desktop-restore-file-buffer,
-           ;; coding-system-for-read may be non-nil.  Reset it before
-           ;; writing to .emacs.
-           (if (or custom-file user-init-file)
-               (let ((coding-system-for-read nil))
-                 (customize-save-variable
-                  'safe-local-variable-values
-                  safe-local-variable-values))))
-         (kill-buffer buf)
-         (or (= char ?!)
-             (= char ?\s)
-             (= char ?y)))))))
+         (insert "\n\n"))
+       (dolist (elt all-vars)
+         (cond ((member elt unsafe-vars)
+                (insert "  * "))
+               ((member elt risky-vars)
+                (insert " ** "))
+               (t
+                (insert "    ")))
+         (princ (car elt) buf)
+         (insert " : ")
+         ;; Make strings with embedded whitespace easier to read.
+         (let ((print-escape-newlines t))
+           (prin1 (cdr elt) buf))
+         (insert "\n"))
+       (setq prompt
+             (format "Please type %s%s: "
+                     (if offer-save "y, n, or !" "y or n")
+                     (if (< (line-number-at-pos) (window-body-height))
+                         ""
+                       (push ?\C-v exit-chars)
+                       ", or C-v to scroll")))
+       (goto-char (point-min))
+       (while (null char)
+         (setq char (read-char-choice prompt exit-chars t))
+         (when (eq char ?\C-v)
+           (condition-case nil
+               (scroll-up)
+             (error (goto-char (point-min))))
+           (setq char nil)))
+       (kill-buffer buf)
+       (when (and offer-save (= char ?!) unsafe-vars)
+         (dolist (elt unsafe-vars)
+           (add-to-list 'safe-local-variable-values elt))
+         ;; When this is called from desktop-restore-file-buffer,
+         ;; coding-system-for-read may be non-nil.  Reset it before
+         ;; writing to .emacs.
+         (if (or custom-file user-init-file)
+             (let ((coding-system-for-read nil))
+               (customize-save-variable
+                'safe-local-variable-values
+                safe-local-variable-values))))
+       (memq char '(?! ?\s ?y))))))
 
 (defun hack-local-variables-prop-line (&optional mode-only)
   "Return local variables specified in the -*- line.
@@ -3119,14 +3195,17 @@ is specified, returning t if it is specified."
          ;; Otherwise, set the variables.
          (enable-local-variables
           (hack-local-variables-filter result nil)
-          (when file-local-variables-alist
-            ;; Any 'evals must run in the Right sequence.
-            (setq file-local-variables-alist
-                  (nreverse file-local-variables-alist))
-            (run-hooks 'before-hack-local-variables-hook)
-            (dolist (elt file-local-variables-alist)
-              (hack-one-local-variable (car elt) (cdr elt))))
-          (run-hooks 'hack-local-variables-hook)))))
+          (hack-local-variables-apply)))))
+
+(defun hack-local-variables-apply ()
+  (when file-local-variables-alist
+    ;; Any 'evals must run in the Right sequence.
+    (setq file-local-variables-alist
+         (nreverse file-local-variables-alist))
+    (run-hooks 'before-hack-local-variables-hook)
+    (dolist (elt file-local-variables-alist)
+      (hack-one-local-variable (car elt) (cdr elt))))
+  (run-hooks 'hack-local-variables-hook))
 
 (defun safe-local-variable-p (sym val)
   "Non-nil if SYM is safe as a file-local variable with value VAL.
@@ -3284,22 +3363,29 @@ ROOT is the root directory of the project.
 Return the new variables list."
   (let* ((file-name (buffer-file-name))
         (sub-file-name (if file-name
+                            ;; FIXME: Why not use file-relative-name?
                            (substring file-name (length root)))))
-    (dolist (entry class-variables variables)
-      (let ((key (car entry)))
-       (cond
-        ((stringp key)
-         ;; Don't include this in the previous condition, because we
-         ;; want to filter all strings before the next condition.
-         (when (and sub-file-name
-                    (>= (length sub-file-name) (length key))
-                    (string= key (substring sub-file-name 0 (length key))))
-           (setq variables (dir-locals-collect-variables
-                            (cdr entry) root variables))))
-        ((or (not key)
-             (derived-mode-p key))
-         (setq variables (dir-locals-collect-mode-variables
-                          (cdr entry) variables))))))))
+    (condition-case err
+        (dolist (entry class-variables variables)
+          (let ((key (car entry)))
+            (cond
+             ((stringp key)
+              ;; Don't include this in the previous condition, because we
+              ;; want to filter all strings before the next condition.
+              (when (and sub-file-name
+                         (>= (length sub-file-name) (length key))
+                         (string-prefix-p key sub-file-name))
+                (setq variables (dir-locals-collect-variables
+                                 (cdr entry) root variables))))
+             ((or (not key)
+                  (derived-mode-p key))
+              (setq variables (dir-locals-collect-mode-variables
+                               (cdr entry) variables))))))
+      (error
+       ;; The file's content might be invalid (e.g. have a merge conflict), but
+       ;; that shouldn't prevent the user from opening the file.
+       (message ".dir-locals error: %s" (error-message-string err))
+       nil))))
 
 (defun dir-locals-set-directory-class (directory class &optional mtime)
   "Declare that the DIRECTORY root is an instance of CLASS.
@@ -3423,15 +3509,16 @@ is found.  Returns the new class name."
 Store the directory-local variables in `dir-local-variables-alist'
 and `file-local-variables-alist', without applying them."
   (when (and enable-local-variables
-            (buffer-file-name)
-            (not (file-remote-p (buffer-file-name))))
+            (not (file-remote-p (or (buffer-file-name) default-directory))))
     ;; Find the variables file.
-    (let ((variables-file (dir-locals-find-file (buffer-file-name)))
+    (let ((variables-file (dir-locals-find-file (or (buffer-file-name) default-directory)))
          (class nil)
          (dir-name nil))
       (cond
        ((stringp variables-file)
-       (setq dir-name (file-name-directory (buffer-file-name)))
+       (setq dir-name (if (buffer-file-name)
+                           (file-name-directory (buffer-file-name))
+                         default-directory))
        (setq class (dir-locals-read-from-file variables-file)))
        ((consp variables-file)
        (setq dir-name (nth 0 variables-file))
@@ -3448,6 +3535,10 @@ and `file-local-variables-alist', without applying them."
              (push elt dir-local-variables-alist))
            (hack-local-variables-filter variables dir-name)))))))
 
+(defun hack-dir-local-variables-non-file-buffer ()
+  (hack-dir-local-variables)
+  (hack-local-variables-apply))
+
 \f
 (defcustom change-major-mode-with-file-name t
   "Non-nil means \\[write-file] should set the major mode from the file name.
@@ -3494,7 +3585,7 @@ the old visited file has been renamed to the new name FILENAME."
       (and buffer (not (eq buffer (current-buffer)))
           (not no-query)
           (not (y-or-n-p (format "A buffer is visiting %s; proceed? "
-                                  filename)))
+                                 filename)))
           (error "Aborted")))
     (or (equal filename buffer-file-name)
        (progn
@@ -3627,10 +3718,13 @@ variable `make-backup-files'.  If it's done by renaming, then the file is
 no longer accessible under its old name.
 
 The value is non-nil after a backup was made by renaming.
-It has the form (MODES . BACKUPNAME).
+It has the form (MODES SELINUXCONTEXT BACKUPNAME).
 MODES is the result of `file-modes' on the original
 file; this means that the caller, after saving the buffer, should change
 the modes of the new file to agree with the old modes.
+SELINUXCONTEXT is the result of `file-selinux-context' on the original
+file; this means that the caller, after saving the buffer, should change
+the SELinux context of the new file to agree with the old context.
 BACKUPNAME is the backup file name, which is the old file renamed."
   (if (and make-backup-files (not backup-inhibited)
           (not buffer-backed-up)
@@ -3658,7 +3752,8 @@ BACKUPNAME is the backup file name, which is the old file renamed."
                            (or delete-old-versions
                                (y-or-n-p (format "Delete excess backup versions of %s? "
                                                  real-file-name)))))
-                     (modes (file-modes buffer-file-name)))
+                     (modes (file-modes buffer-file-name))
+                     (context (file-selinux-context buffer-file-name)))
                  ;; Actually write the back up file.
                  (condition-case ()
                      (if (or file-precious-flag
@@ -3678,10 +3773,10 @@ BACKUPNAME is the backup file name, which is the old file renamed."
                                                   (<= (nth 2 attr) backup-by-copying-when-privileged-mismatch)))
                                          (or (nth 9 attr)
                                              (not (file-ownership-preserved-p real-file-name)))))))
-                         (backup-buffer-copy real-file-name backupname modes)
+                         (backup-buffer-copy real-file-name backupname modes context)
                        ;; rename-file should delete old backup.
                        (rename-file real-file-name backupname t)
-                       (setq setmodes (cons modes backupname)))
+                       (setq setmodes (list modes context backupname)))
                    (file-error
                     ;; If trouble writing the backup, write it in
                     ;; .emacs.d/%backup%.
@@ -3689,7 +3784,7 @@ BACKUPNAME is the backup file name, which is the old file renamed."
                     (message "Cannot write backup file; backing up in %s"
                              backupname)
                     (sleep-for 1)
-                    (backup-buffer-copy real-file-name backupname modes)))
+                    (backup-buffer-copy real-file-name backupname modes context)))
                  (setq buffer-backed-up t)
                  ;; Now delete the old versions, if desired.
                  (if delete-old-versions
@@ -3701,7 +3796,7 @@ BACKUPNAME is the backup file name, which is the old file renamed."
                  setmodes)
            (file-error nil))))))
 
-(defun backup-buffer-copy (from-name to-name modes)
+(defun backup-buffer-copy (from-name to-name modes context)
   (let ((umask (default-file-modes)))
     (unwind-protect
        (progn
@@ -3728,23 +3823,29 @@ BACKUPNAME is the backup file name, which is the old file renamed."
       ;; Reset the umask.
       (set-default-file-modes umask)))
   (and modes
-       (set-file-modes to-name (logand modes #o1777))))
+       (set-file-modes to-name (logand modes #o1777)))
+  (and context
+       (set-file-selinux-context to-name context)))
+
+(defvar file-name-version-regexp
+  "\\(?:~\\|\\.~[-[:alnum:]:#@^._]+~\\)"
+  "Regular expression matching the backup/version part of a file name.
+Used by `file-name-sans-versions'.")
 
 (defun file-name-sans-versions (name &optional keep-backup-version)
   "Return file NAME sans backup versions or strings.
 This is a separate procedure so your site-init or startup file can
 redefine it.
 If the optional argument KEEP-BACKUP-VERSION is non-nil,
-we do not remove backup version numbers, only true file version numbers."
+we do not remove backup version numbers, only true file version numbers.
+See also `file-name-version-regexp'."
   (let ((handler (find-file-name-handler name 'file-name-sans-versions)))
     (if handler
        (funcall handler 'file-name-sans-versions name keep-backup-version)
       (substring name 0
-                (if keep-backup-version
-                    (length name)
-                  (or (string-match "\\.~[-[:alnum:]:#@^._]+~\\'" name)
-                      (string-match "~\\'" name)
-                      (length name)))))))
+                (unless keep-backup-version
+                   (string-match (concat file-name-version-regexp "\\'")
+                                 name))))))
 
 (defun file-ownership-preserved-p (file)
   "Return t if deleting FILE and rewriting it would preserve the owner."
@@ -4237,8 +4338,9 @@ Before and after saving the buffer, this function runs
          (or (verify-visited-file-modtime (current-buffer))
              (not (file-exists-p buffer-file-name))
              (yes-or-no-p
-              (format "%s has changed since visited or saved.  Save anyway? "
-                      (file-name-nondirectory buffer-file-name)))
+              (format
+               "%s has changed since visited or saved.  Save anyway? "
+               (file-name-nondirectory buffer-file-name)))
              (error "Save not confirmed"))
          (save-restriction
            (widen)
@@ -4276,7 +4378,9 @@ Before and after saving the buffer, this function runs
                  (nthcdr 10 (file-attributes buffer-file-name)))
            (if setmodes
                (condition-case ()
-                   (set-file-modes buffer-file-name (car setmodes))
+                   (progn
+                     (set-file-modes buffer-file-name (car setmodes))
+                     (set-file-selinux-context buffer-file-name (nth 1 setmodes)))
                  (error nil))))
          ;; If the auto-save file was recent before this command,
          ;; delete it now.
@@ -4289,7 +4393,7 @@ Before and after saving the buffer, this function runs
 ;; This does the "real job" of writing a buffer into its visited file
 ;; and making a backup file.  This is what is normally done
 ;; but inhibited if one of write-file-functions returns non-nil.
-;; It returns a value (MODES . BACKUPNAME), like backup-buffer.
+;; It returns a value (MODES SELINUXCONTEXT BACKUPNAME), like backup-buffer.
 (defun basic-save-buffer-1 ()
   (prog1
       (if save-buffer-coding-system
@@ -4301,7 +4405,7 @@ Before and after saving the buffer, this function runs
       (setq buffer-file-coding-system-explicit
            (cons last-coding-system-used nil)))))
 
-;; This returns a value (MODES . BACKUPNAME), like backup-buffer.
+;; This returns a value (MODES SELINUXCONTEXT BACKUPNAME), like backup-buffer.
 (defun basic-save-buffer-2 ()
   (let (tempsetmodes setmodes)
     (if (not (file-writable-p buffer-file-name))
@@ -4313,9 +4417,10 @@ Before and after saving the buffer, this function runs
            (if (not (file-exists-p buffer-file-name))
                (error "Directory %s write-protected" dir)
              (if (yes-or-no-p
-                  (format "File %s is write-protected; try to save anyway? "
-                          (file-name-nondirectory
-                           buffer-file-name)))
+                  (format
+                   "File %s is write-protected; try to save anyway? "
+                   (file-name-nondirectory
+                    buffer-file-name)))
                  (setq tempsetmodes t)
                (error "Attempt to save to a file which you aren't allowed to write"))))))
     (or buffer-backed-up
@@ -4372,8 +4477,9 @@ Before and after saving the buffer, this function runs
            ;; Since we have created an entirely new file,
            ;; make sure it gets the right permission bits set.
            (setq setmodes (or setmodes
-                              (cons (or (file-modes buffer-file-name)
+                              (list (or (file-modes buffer-file-name)
                                         (logand ?\666 umask))
+                                    (file-selinux-context buffer-file-name)
                                     buffer-file-name)))
            ;; We succeeded in writing the temp file,
            ;; so rename it.
@@ -4384,8 +4490,11 @@ Before and after saving the buffer, this function runs
        ;; (setmodes is set) because that says we're superseding.
        (cond ((and tempsetmodes (not setmodes))
               ;; Change the mode back, after writing.
-              (setq setmodes (cons (file-modes buffer-file-name) buffer-file-name))
-              (set-file-modes buffer-file-name (logior (car setmodes) 128))))
+              (setq setmodes (list (file-modes buffer-file-name)
+                                   (file-selinux-context buffer-file-name)
+                                   buffer-file-name))
+              (set-file-modes buffer-file-name (logior (car setmodes) 128))
+              (set-file-selinux-context buffer-file-name (nth 1 setmodes)))))
        (let (success)
          (unwind-protect
              (progn
@@ -4399,32 +4508,12 @@ Before and after saving the buffer, this function runs
            ;; the backup by renaming, undo the backing-up.
            (and setmodes (not success)
                 (progn
-                  (rename-file (cdr setmodes) buffer-file-name t)
-                  (setq buffer-backed-up nil)))))))
+                  (rename-file (nth 2 setmodes) buffer-file-name t)
+                  (setq buffer-backed-up nil))))))
     setmodes))
 
-(defun diff-buffer-with-file (&optional buffer)
-  "View the differences between BUFFER and its associated file.
-This requires the external program `diff' to be in your `exec-path'."
-  (interactive "bBuffer: ")
-  (with-current-buffer (get-buffer (or buffer (current-buffer)))
-    (if (and buffer-file-name
-            (file-exists-p buffer-file-name))
-       (let ((tempfile (make-temp-file "buffer-content-")))
-         (unwind-protect
-             (progn
-               (write-region nil nil tempfile nil 'nomessage)
-               (diff buffer-file-name tempfile nil t)
-               (sit-for 0))
-           (when (file-exists-p tempfile)
-             (delete-file tempfile))))
-      (message "Buffer %s has no associated file on disc" (buffer-name))
-      ;; Display that message for 1 second so that user can read it
-      ;; in the minibuffer.
-      (sit-for 1)))
-  ;; return always nil, so that save-buffers-kill-emacs will not move
-  ;; over to the next unsaved buffer when calling `d'.
-  nil)
+(declare-function diff-no-select "diff"
+                 (old new &optional switches no-async buf))
 
 (defvar save-some-buffers-action-alist
   `((?\C-r
@@ -4440,13 +4529,14 @@ This requires the external program `diff' to be in your `exec-path'."
     (?d ,(lambda (buf)
            (if (null (buffer-file-name buf))
                (message "Not applicable: no file")
-             (save-window-excursion (diff-buffer-with-file buf))
-             (if (not enable-recursive-minibuffers)
-                 (progn (display-buffer (get-buffer-create "*Diff*"))
-                        (setq other-window-scroll-buffer "*Diff*"))
-               (view-buffer (get-buffer-create "*Diff*")
-                            (lambda (_) (exit-recursive-edit)))
-               (recursive-edit)))
+             (require 'diff)            ;for diff-no-select.
+             (let ((diffbuf (diff-no-select (buffer-file-name buf) buf
+                                            nil 'noasync)))
+               (if (not enable-recursive-minibuffers)
+                   (progn (display-buffer diffbuf)
+                          (setq other-window-scroll-buffer diffbuf))
+                 (view-buffer diffbuf (lambda (_) (exit-recursive-edit)))
+                 (recursive-edit))))
            ;; Return nil to ask about BUF again.
            nil)
        ,(purecopy "view changes in this buffer")))
@@ -4521,8 +4611,7 @@ change the additional actions you can take on files."
           (progn
             (if (or arg
                     (eq save-abbrevs 'silently)
-                    (y-or-n-p (format "Save abbrevs in %s? "
-                                      abbrev-file-name)))
+                    (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name)))
                 (write-abbrev-file nil))
             ;; Don't keep bothering user if he says no.
             (setq abbrevs-changed nil)
@@ -4636,16 +4725,17 @@ or multiple mail buffers, etc."
       (force-mode-line-update))))
 
 (defun make-directory (dir &optional parents)
-  "Create the directory DIR and any nonexistent parent dirs.
-If DIR already exists as a directory, signal an error, unless PARENTS is set.
+  "Create the directory DIR and optionally any nonexistent parent dirs.
+If DIR already exists as a directory, signal an error, unless
+PARENTS is non-nil.
 
-Interactively, the default choice of directory to create
-is the current default directory for file names.
-That is useful when you have visited a file in a nonexistent directory.
+Interactively, the default choice of directory to create is the
+current buffer's default directory.  That is useful when you have
+visited a file in a nonexistent directory.
 
-Noninteractively, the second (optional) argument PARENTS says whether
-to create parent directories if they don't exist.  Interactively,
-this happens by default."
+Noninteractively, the second (optional) argument PARENTS, if
+non-nil, says whether to create parent directories that don't
+exist.  Interactively, this happens by default."
   (interactive
    (list (read-file-name "Make directory: " default-directory default-directory
                         nil nil)
@@ -4676,19 +4766,30 @@ this happens by default."
   "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   "Regexp matching any file name except \".\" and \"..\".")
 
-(defun delete-directory (directory &optional recursive)
+(defun delete-directory (directory &optional recursive trash)
   "Delete the directory named DIRECTORY.  Does not follow symlinks.
-If RECURSIVE is non-nil, all files in DIRECTORY are deleted as well."
+If RECURSIVE is non-nil, all files in DIRECTORY are deleted as well.
+TRASH non-nil means to trash the directory instead, provided
+`delete-by-moving-to-trash' is non-nil.
+
+When called interactively, TRASH is t if no prefix argument is
+given.  With a prefix argument, TRASH is nil."
   (interactive
-   (let ((dir (expand-file-name
-              (read-file-name
-               "Delete directory: "
-               default-directory default-directory nil nil))))
+   (let* ((trashing (and delete-by-moving-to-trash
+                        (null current-prefix-arg)))
+         (dir (expand-file-name
+               (read-file-name
+                (if trashing
+                    "Move directory to trash: "
+                  "Delete directory: ")
+                default-directory default-directory nil nil))))
      (list dir
           (if (directory-files dir nil directory-files-no-dot-files-regexp)
               (y-or-n-p
-               (format "Directory `%s' is not empty, really delete? " dir))
-            nil))))
+               (format "Directory `%s' is not empty, really %s? "
+                       dir (if trashing "trash" "delete")))
+            nil)
+          (null current-prefix-arg))))
   ;; If default-directory is a remote directory, make sure we find its
   ;; delete-directory handler.
   (setq directory (directory-file-name (expand-file-name directory)))
@@ -4696,7 +4797,7 @@ If RECURSIVE is non-nil, all files in DIRECTORY are deleted as well."
     (cond
      (handler
       (funcall handler 'delete-directory directory recursive))
-     (delete-by-moving-to-trash
+     ((and delete-by-moving-to-trash trash)
       ;; Only move non-empty dir to trash if recursive deletion was
       ;; requested.  This mimics the non-`delete-by-moving-to-trash'
       ;; case, where the operation fails in delete-directory-internal.
@@ -4716,8 +4817,8 @@ If RECURSIVE is non-nil, all files in DIRECTORY are deleted as well."
                  ;; (and (file-directory-p fn) (not (file-symlink-p fn)))
                  ;; but more efficient
                  (if (eq t (car (file-attributes file)))
-                     (delete-directory file recursive)
-                   (delete-file file)))
+                     (delete-directory file recursive nil)
+                   (delete-file file nil)))
                ;; We do not want to delete "." and "..".
                (directory-files
                 directory 'full directory-files-no-dot-files-regexp)))
@@ -5126,10 +5227,10 @@ This command is used in the special Dired buffer created by
 
 (defun kill-buffer-ask (buffer)
   "Kill BUFFER if confirmed."
-  (when (yes-or-no-p
-         (format "Buffer %s %s.  Kill? " (buffer-name buffer)
-                 (if (buffer-modified-p buffer)
-                     "HAS BEEN EDITED" "is unmodified")))
+  (when (yes-or-no-p (format "Buffer %s %s.  Kill? "
+                            (buffer-name buffer)
+                            (if (buffer-modified-p buffer)
+                                "HAS BEEN EDITED" "is unmodified")))
     (kill-buffer buffer)))
 
 (defun kill-some-buffers (&optional list)
@@ -5161,30 +5262,6 @@ The optional second argument indicates whether to kill internal buffers too."
         (kill-buffer-ask buffer)))))
 
 \f
-(defun auto-save-mode (arg)
-  "Toggle auto-saving of contents of current buffer.
-With prefix argument ARG, turn auto-saving on if positive, else off."
-  (interactive "P")
-  (setq buffer-auto-save-file-name
-        (and (if (null arg)
-                (or (not buffer-auto-save-file-name)
-                    ;; If auto-save is off because buffer has shrunk,
-                    ;; then toggling should turn it on.
-                    (< buffer-saved-size 0))
-              (or (eq arg t) (listp arg) (and (integerp arg) (> arg 0))))
-            (if (and buffer-file-name auto-save-visited-file-name
-                     (not buffer-read-only))
-                buffer-file-name
-              (make-auto-save-file-name))))
-  ;; If -1 was stored here, to temporarily turn off saving,
-  ;; turn it back on.
-  (and (< buffer-saved-size 0)
-       (setq buffer-saved-size 0))
-  (if (called-interactively-p 'interactive)
-      (message "Auto-save %s (in this buffer)"
-              (if buffer-auto-save-file-name "on" "off")))
-  buffer-auto-save-file-name)
-
 (defun rename-auto-save-file ()
   "Adjust current buffer's auto save file name for current conditions.
 Also rename any existing auto save file, if it was made in this session."
@@ -5548,12 +5625,14 @@ preference to the program given by this variable."
 
 (defun get-free-disk-space (dir)
   "Return the amount of free space on directory DIR's file system.
-The result is a string that gives the number of free 1KB blocks,
-or nil if the system call or the program which retrieve the information
-fail.  It returns also nil when DIR is a remote directory.
-
-This function calls `file-system-info' if it is available, or invokes the
-program specified by `directory-free-space-program' if that is non-nil."
+The return value is a string describing the amount of free
+space (normally, the number of free 1KB blocks).
+
+This function calls `file-system-info' if it is available, or
+invokes the program specified by `directory-free-space-program'
+and `directory-free-space-args'.  If the system call or program
+is unsuccessful, or if DIR is a remote directory, this function
+returns nil."
   (unless (file-remote-p dir)
     ;; Try to find the number of free blocks.  Non-Posix systems don't
     ;; always have df, but might have an equivalent system call.
@@ -5573,19 +5652,17 @@ program specified by `directory-free-space-program' if that is non-nil."
                                         directory-free-space-args
                                         dir)
                           0)))
-           ;; Usual format is a header line followed by a line of
-           ;; numbers.
+           ;; Assume that the "available" column is before the
+           ;; "capacity" column.  Find the "%" and scan backward.
            (goto-char (point-min))
            (forward-line 1)
-           (if (not (eobp))
-               (progn
-                 ;; Move to the end of the "available blocks" number.
-                 (skip-chars-forward "^ \t")
-                 (forward-word 3)
-                 ;; Copy it into AVAILABLE.
-                 (let ((end (point)))
-                   (forward-word -1)
-                   (buffer-substring (point) end))))))))))
+           (when (re-search-forward
+                  "[[:space:]]+[^[:space:]]+%[^%]*$"
+                  (line-end-position) t)
+             (goto-char (match-beginning 0))
+             (let ((endpt (point)))
+               (skip-chars-backward "^[:space:]")
+               (buffer-substring-no-properties (point) endpt)))))))))
 
 ;; The following expression replaces `dired-move-to-filename-regexp'.
 (defvar directory-listing-before-filename-regexp
@@ -6374,5 +6451,4 @@ Otherwise, trash FILENAME using the freedesktop.org conventions,
 (define-key ctl-x-5-map "r" 'find-file-read-only-other-frame)
 (define-key ctl-x-5-map "\C-o" 'display-buffer-other-frame)
 
-;; arch-tag: bc68d3ea-19ca-468b-aac6-3a4a7766101f
 ;;; files.el ends here