]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
Update docs for `customize-mode'
[gnu-emacs] / lisp / files.el
index fdda9b2a77e49be4530ede13692e6cd461b0f73e..1f97fa5f52fba3a67c5c654c620f87e6282362f3 100644 (file)
@@ -1,6 +1,6 @@
 ;;; files.el --- file input and output commands for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1987, 1992-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1992-2016 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
@@ -740,20 +740,27 @@ The path separator is colon in GNU and GNU-like systems."
        (error "No such directory found via CDPATH environment variable"))))
 
 (defsubst directory-name-p (name)
-  "Return non-nil if NAME ends with a slash character."
-  (and (> (length name) 0)
-       (char-equal (aref name (1- (length name))) ?/)))
-
-(defun directory-files-recursively (dir match &optional include-directories)
-  "Return all files under DIR that have file names matching MATCH (a regexp).
+  "Return non-nil if NAME ends with a directory separator character."
+  (let ((len (length name))
+        (lastc ?.))
+    (if (> len 0)
+        (setq lastc (aref name (1- len))))
+    (or (= lastc ?/)
+        (and (memq system-type '(windows-nt ms-dos))
+             (= lastc ?\\)))))
+
+(defun directory-files-recursively (dir regexp &optional include-directories)
+  "Return list of all files under DIR that have file names matching REGEXP.
 This function works recursively.  Files are returned in \"depth first\"
-and alphabetical order.
-If INCLUDE-DIRECTORIES, also include directories that have matching names."
+order, and files from each directory are sorted in alphabetical order.
+Each file name appears in the returned list in its absolute form.
+Optional argument INCLUDE-DIRECTORIES non-nil means also include in the
+output directories whose names match REGEXP."
   (let ((result nil)
        (files nil)
        ;; When DIR is "/", remote file names like "/method:" could
        ;; also be offered.  We shall suppress them.
-       (tramp-mode (and tramp-mode (file-remote-p dir))))
+       (tramp-mode (and tramp-mode (file-remote-p (expand-file-name dir)))))
     (dolist (file (sort (file-name-all-completions "" dir)
                        'string<))
       (unless (member file '("./" "../"))
@@ -764,19 +771,23 @@ If INCLUDE-DIRECTORIES, also include directories that have matching names."
              (unless (file-symlink-p full-file)
                (setq result
                      (nconc result (directory-files-recursively
-                                    full-file match include-directories))))
+                                    full-file regexp include-directories))))
              (when (and include-directories
-                        (string-match match leaf))
+                        (string-match regexp leaf))
                (setq result (nconc result (list full-file)))))
-         (when (string-match match file)
+         (when (string-match regexp file)
            (push (expand-file-name file dir) files)))))
     (nconc result (nreverse files))))
 
+(defvar module-file-suffix)
+
 (defun load-file (file)
   "Load the Lisp file named FILE."
-  ;; This is a case where .elc makes a lot of sense.
+  ;; This is a case where .elc and .so/.dll make a lot of sense.
   (interactive (list (let ((completion-ignored-extensions
-                           (remove ".elc" completion-ignored-extensions)))
+                            (remove module-file-suffix
+                                    (remove ".elc"
+                                            completion-ignored-extensions))))
                       (read-file-name "Load file: " nil nil 'lambda))))
   (load (expand-file-name file) nil nil t))
 
@@ -787,8 +798,8 @@ return nil.
 PATH should be a list of directories to look in, like the lists in
 `exec-path' or `load-path'.
 If SUFFIXES is non-nil, it should be a list of suffixes to append to
-file name when searching.  If SUFFIXES is nil, it is equivalent to '(\"\").
-Use '(\"/\") to disable PATH search, but still try the suffixes in SUFFIXES.
+file name when searching.  If SUFFIXES is nil, it is equivalent to (\"\").
+Use (\"/\") to disable PATH search, but still try the suffixes in SUFFIXES.
 If non-nil, PREDICATE is used instead of `file-readable-p'.
 
 This function will normally skip directories, so if you want it to find
@@ -1012,6 +1023,7 @@ Return nil if COMMAND is not found anywhere in `exec-path'."
 
 (defun load-library (library)
   "Load the Emacs Lisp library named LIBRARY.
+LIBRARY should be a string.
 This is an interface to the function `load'.  LIBRARY is searched
 for in `load-path', both with and without `load-suffixes' (as
 well as `load-file-rep-suffixes').
@@ -1019,10 +1031,11 @@ well as `load-file-rep-suffixes').
 See Info node `(emacs)Lisp Libraries' for more details.
 See `load-file' for a different interface to `load'."
   (interactive
-   (list (completing-read "Load library: "
-                         (apply-partially 'locate-file-completion-table
-                                           load-path
-                                           (get-load-suffixes)))))
+   (let (completion-ignored-extensions)
+     (list (completing-read "Load library: "
+                            (apply-partially 'locate-file-completion-table
+                                             load-path
+                                             (get-load-suffixes))))))
   (load library))
 
 (defun file-remote-p (file &optional identification connected)
@@ -1418,8 +1431,10 @@ return value, which may be passed as the REQUIRE-MATCH arg to
 
 (defmacro minibuffer-with-setup-hook (fun &rest body)
   "Temporarily add FUN to `minibuffer-setup-hook' while executing BODY.
-FUN can also be (:append FUN1), in which case FUN1 is appended to
-`minibuffer-setup-hook'.
+
+By default, FUN is prepended to `minibuffer-setup-hook'.  But if FUN is of
+the form `(:append FUN1)', FUN1 will be appended to `minibuffer-setup-hook'
+instead of prepending it.
 
 BODY should use the minibuffer at most once.
 Recursive uses of the minibuffer are unaffected (FUN is not
@@ -2128,6 +2143,7 @@ Do you want to revisit the file normally now? ")
 \f
 (defun insert-file-contents-literally (filename &optional visit beg end replace)
   "Like `insert-file-contents', but only reads in the file literally.
+See `insert-file-contents' for an explanation of the parameters.
 A buffer may be modified in several ways after reading into the buffer,
 due to Emacs features such as format decoding, character code
 conversion, `find-file-hook', automatic uncompression, etc.
@@ -3407,11 +3423,15 @@ local variables, but directory-local variables may still be applied."
                               (unless hack-local-variables--warned-lexical
                                 (setq hack-local-variables--warned-lexical t)
                                 (display-warning
-                                  :warning
+                                  'files
                                   (format-message
                                    "%s: `lexical-binding' at end of file unreliable"
                                    (file-name-nondirectory
-                                    (or buffer-file-name ""))))))
+                                    ;; We are called from
+                                    ;; 'with-temp-buffer', so we need
+                                    ;; to use 'thisbuf's name in the
+                                    ;; warning message.
+                                    (or (buffer-file-name thisbuf) ""))))))
                              (t
                               (ignore-errors
                                 (push (cons (if (eq var 'eval)
@@ -3648,7 +3668,7 @@ Return the new variables list."
       (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 "%s error: %s" dir-locals-file (error-message-string err))
+       (message ".dir-locals error: %s" (error-message-string err))
        nil))))
 
 (defun dir-locals-set-directory-class (directory class &optional mtime)
@@ -3698,33 +3718,10 @@ VARIABLES list of the class.  The list is processed in order.
   applied by recursively following these rules."
   (setf (alist-get class dir-locals-class-alist) variables))
 
-(defconst dir-locals-file ".dir-locals*.el"
-  "Pattern for files that contain directory-local variables.
-It has to be constant to enforce uniform values across different
-environments and users.
-
-Multiple dir-locals files in the same directory are loaded in
-`string<' order.
-See Info node `(elisp)Directory Local Variables' for details.")
-
-(defun dir-locals--all-files (file-or-dir)
-  "Return a list of all readable dir-locals files matching FILE-OR-DIR.
-If FILE-OR-DIR is a file pattern, expand wildcards in it and
-return a sorted list of the results.  If it is a directory name,
-return a sorted list of all files matching `dir-locals-file' in
-this directory.
-The returned list is sorted by `string<' order."
-  (require 'seq)
-  (let ((default-directory (if (file-directory-p file-or-dir)
-                               file-or-dir
-                             default-directory)))
-    (seq-filter (lambda (f) (and (file-readable-p f)
-                            (file-regular-p f)))
-                (file-expand-wildcards
-                 (cond ((not (file-directory-p file-or-dir)) file-or-dir)
-                       ((eq system-type 'ms-dos) (dosified-file-name dir-locals-file))
-                       (t dir-locals-file))
-                 'full))))
+(defconst dir-locals-file ".dir-locals.el"
+  "File that contains directory-local variables.
+It has to be constant to enforce uniform values
+across different environments and users.")
 
 (defun dir-locals-find-file (file)
   "Find the directory-local variables for FILE.
@@ -3742,93 +3739,75 @@ If not, the cache entry is cleared so that the file will be re-read.
 This function returns either nil (no directory local variables found),
 or the matching entry from `dir-locals-directory-cache' (a list),
 or the full path to the `dir-locals-file' (a string) in the case
-of no valid cache entry.  If `dir-locals-file' contains
-wildcards, then the return value is not a proper filename, it is
-an absolute version of `dir-locals-file' which is guaranteed to
-expand to at least one file."
+of no valid cache entry."
   (setq file (expand-file-name file))
-  (let* ((locals-dir (locate-dominating-file (file-name-directory file)
-                                             #'dir-locals--all-files))
-         locals-file dir-elt)
+  (let* ((dir-locals-file-name
+         (if (eq system-type 'ms-dos)
+             (dosified-file-name dir-locals-file)
+           dir-locals-file))
+        (locals-file (locate-dominating-file file dir-locals-file-name))
+        (dir-elt nil))
     ;; `locate-dominating-file' may have abbreviated the name.
-    (when locals-dir
-      (setq locals-dir (expand-file-name locals-dir))
-      (setq locals-file (expand-file-name (if (eq system-type 'ms-dos)
-                                              (dosified-file-name dir-locals-file)
-                                            dir-locals-file)
-                                          locals-dir)))
+    (and locals-file
+        (setq locals-file (expand-file-name dir-locals-file-name locals-file)))
+        ;; Let dir-locals-read-from-file inform us via demoted-errors
+        ;; about unreadable files, etc.
+        ;; Maybe we'd want to keep searching though - that is
+        ;; a locate-dominating-file issue.
+;;;     (or (not (file-readable-p locals-file))
+;;;         (not (file-regular-p locals-file)))
+;;;     (setq locals-file nil))
     ;; Find the best cached value in `dir-locals-directory-cache'.
     (dolist (elt dir-locals-directory-cache)
       (when (and (string-prefix-p (car elt) file
-                                  (memq system-type
-                                        '(windows-nt cygwin ms-dos)))
-                 (> (length (car elt)) (length (car dir-elt))))
-        (setq dir-elt elt)))
+                                 (memq system-type
+                                       '(windows-nt cygwin ms-dos)))
+                (> (length (car elt)) (length (car dir-elt))))
+       (setq dir-elt elt)))
     (if (and dir-elt
-             (or (null locals-dir)
-                 (<= (length locals-dir)
-                     (length (car dir-elt)))))
-        ;; Found a potential cache entry.  Check validity.
-        ;; A cache entry with no MTIME is assumed to always be valid
-        ;; (ie, set directly, not from a dir-locals file).
-        ;; Note, we don't bother to check that there is a matching class
-        ;; element in dir-locals-class-alist, since that's done by
-        ;; dir-locals-set-directory-class.
-        (if (or (null (nth 2 dir-elt))
-                (let ((cached-files (dir-locals--all-files (car dir-elt))))
-                  ;; The entry MTIME should match the most recent
-                  ;; MTIME among matching files.
-                  (and cached-files
-                       (= (time-to-seconds (nth 2 dir-elt))
-                          (apply #'max (mapcar (lambda (f) (time-to-seconds (nth 5 (file-attributes f))))
-                                               cached-files))))))
-            ;; This cache entry is OK.
-            dir-elt
-          ;; This cache entry is invalid; clear it.
-          (setq dir-locals-directory-cache
-                (delq dir-elt dir-locals-directory-cache))
-          ;; Return the first existing dir-locals file.  Might be the same
-          ;; as dir-elt's, might not (eg latter might have been deleted).
-          locals-file)
+            (or (null locals-file)
+                (<= (length (file-name-directory locals-file))
+                    (length (car dir-elt)))))
+       ;; Found a potential cache entry.  Check validity.
+       ;; A cache entry with no MTIME is assumed to always be valid
+       ;; (ie, set directly, not from a dir-locals file).
+       ;; Note, we don't bother to check that there is a matching class
+       ;; element in dir-locals-class-alist, since that's done by
+       ;; dir-locals-set-directory-class.
+       (if (or (null (nth 2 dir-elt))
+               (let ((cached-file (expand-file-name dir-locals-file-name
+                                                    (car dir-elt))))
+                 (and (file-readable-p cached-file)
+                      (equal (nth 2 dir-elt)
+                             (nth 5 (file-attributes cached-file))))))
+           ;; This cache entry is OK.
+           dir-elt
+         ;; This cache entry is invalid; clear it.
+         (setq dir-locals-directory-cache
+               (delq dir-elt dir-locals-directory-cache))
+         ;; Return the first existing dir-locals file.  Might be the same
+         ;; as dir-elt's, might not (eg latter might have been deleted).
+         locals-file)
       ;; No cache entry.
       locals-file)))
 
 (defun dir-locals-read-from-file (file)
   "Load a variables FILE and register a new class and instance.
-FILE is the absolute name of the file holding the variables to
-apply.  It may contain wildcards.
+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."
-  (require 'map)
-  (let* ((dir-name (file-name-directory file))
-         (class-name (intern dir-name))
-         (files (dir-locals--all-files file))
-         (read-circle nil)
-         (success nil)
-         (variables))
+  (with-temp-buffer
     (with-demoted-errors "Error reading dir-locals: %S"
-      (dolist (file files)
-        (with-temp-buffer
-          (insert-file-contents file)
-          (condition-case-unless-debug nil
-              (setq variables
-                    (map-merge-with 'list (lambda (a b) (map-merge 'list a b))
-                                    variables
-                                    (read (current-buffer))))
-            (end-of-file nil))))
-      (setq success t))
-    (dir-locals-set-class-variables class-name variables)
-    (dir-locals-set-directory-class
-     dir-name class-name
-     (seconds-to-time
-      (if success
-          (apply #'max (mapcar (lambda (file)
-                                 (time-to-seconds (nth 5 (file-attributes file))))
-                               files))
-        ;; If there was a problem, use the values we could get but
-        ;; don't let the cache prevent future reads.
-        0)))
-    class-name))
+      (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."
@@ -3851,17 +3830,17 @@ This does nothing if either `enable-local-variables' or
                 (not (file-remote-p (or (buffer-file-name)
                                         default-directory)))))
     ;; Find the variables file.
-    (let ((file-pattern-or-cache (dir-locals-find-file
-                                  (or (buffer-file-name) default-directory)))
+    (let ((variables-file (dir-locals-find-file
+                           (or (buffer-file-name) default-directory)))
          (class nil)
          (dir-name nil))
       (cond
-       ((stringp file-pattern-or-cache)
-       (setq dir-name (file-name-directory file-pattern-or-cache)
-             class (dir-locals-read-from-file file-pattern-or-cache)))
-       ((consp file-pattern-or-cache)
-       (setq dir-name (nth 0 file-pattern-or-cache))
-       (setq class (nth 1 file-pattern-or-cache))))
+       ((stringp variables-file)
+       (setq dir-name (file-name-directory variables-file)
+             class (dir-locals-read-from-file variables-file)))
+       ((consp variables-file)
+       (setq dir-name (nth 0 variables-file))
+       (setq class (nth 1 variables-file))))
       (when class
        (let ((variables
               (dir-locals-collect-variables
@@ -3871,7 +3850,7 @@ This does nothing if either `enable-local-variables' or
              (if (eq (car elt) 'coding)
                   (unless hack-dir-local-variables--warned-coding
                     (setq hack-dir-local-variables--warned-coding t)
-                    (display-warning :warning
+                    (display-warning 'files
                                      "Coding cannot be specified by dir-locals"))
                (unless (memq (car elt) '(eval mode))
                  (setq dir-local-variables-alist
@@ -4278,8 +4257,8 @@ the group would be preserved too."
 
 (defun file-name-sans-extension (filename)
   "Return FILENAME sans final \"extension\".
-The extension, in a file name, is the part that follows the last `.',
-except that a leading `.', if any, doesn't count."
+The extension, in a file name, is the part that begins with the last `.',
+except that a leading `.' of the file name, if there is one, doesn't count."
   (save-match-data
     (let ((file (file-name-sans-versions (file-name-nondirectory filename)))
          directory)
@@ -4294,15 +4273,16 @@ except that a leading `.', if any, doesn't count."
 
 (defun file-name-extension (filename &optional period)
   "Return FILENAME's final \"extension\".
-The extension, in a file name, is the part that follows the last `.',
-excluding version numbers and backup suffixes,
-except that a leading `.', if any, doesn't count.
+The extension, in a file name, is the part that begins with the last `.',
+excluding version numbers and backup suffixes, except that a leading `.'
+of the file name, if there is one, doesn't count.
 Return nil for extensionless file names such as `foo'.
 Return the empty string for file names such as `foo.'.
 
-If PERIOD is non-nil, then the returned value includes the period
-that delimits the extension, and if FILENAME has no extension,
-the value is \"\"."
+By default, the returned value excludes the period that starts the
+extension, but if the optional argument PERIOD is non-nil, the period
+is included in the value, and in that case, if FILENAME has no
+extension, the value is \"\"."
   (save-match-data
     (let ((file (file-name-sans-versions (file-name-nondirectory filename))))
       (if (and (string-match "\\.[^.]*\\'" file)
@@ -5096,7 +5076,7 @@ change the additional actions you can take on files."
 \f
 (defun clear-visited-file-modtime ()
   "Clear out records of last mod time of visited file.
-Next attempt to save will certainly not complain of a discrepancy."
+Next attempt to save will not complain of a discrepancy."
   (set-visited-file-modtime 0))
 
 (defun not-modified (&optional arg)
@@ -6167,7 +6147,7 @@ and `list-directory-verbose-switches'."
 
 PATTERN is assumed to represent a file-name wildcard suitable for the
 underlying filesystem.  For Unix and GNU/Linux, each character from the
-set [ \\t\\n;<>&|()`'\"#$] is quoted with a backslash; for DOS/Windows, all
+set [ \\t\\n;<>&|()\\=`\\='\"#$] is quoted with a backslash; for DOS/Windows, all
 the parts of the pattern which don't include wildcard characters are
 quoted with double quotes.
 
@@ -6242,7 +6222,7 @@ 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)
+  (unless (file-remote-p (expand-file-name dir))
     ;; Try to find the number of free blocks.  Non-Posix systems don't
     ;; always have df, but might have an equivalent system call.
     (if (fboundp 'file-system-info)
@@ -6542,7 +6522,7 @@ normally equivalent short `-D' option is just passed on to
                  (setq error-lines (nreverse error-lines))
                  ;; Now read the numeric positions of file names.
                  (goto-char linebeg)
-                 (forward-word 1)
+                 (forward-word-strictly 1)
                  (forward-char 3)
                  (while (< (point) end)
                    (let ((start (insert-directory-adj-pos
@@ -6817,8 +6797,8 @@ If CHAR is in [Xugo], the value is taken from FROM (or 0 if omitted)."
   (cond ((= char ?r) #o0444)
        ((= char ?w) #o0222)
        ((= char ?x) #o0111)
-       ((= char ?s) #o1000)
-       ((= char ?t) #o6000)
+       ((= char ?s) #o6000)
+       ((= char ?t) #o1000)
        ;; Rights relative to the previous file modes.
        ((= char ?X) (if (= (logand from #o111) 0) 0 #o0111))
        ((= char ?u) (let ((uright (logand #o4700 from)))
@@ -6874,7 +6854,7 @@ as in \"og+rX-w\"."
                                  (mapcar 'file-modes-char-to-who
                                          (match-string 1 modes)))))
              (when (= num-who 0)
-               (setq num-who (default-file-modes)))
+               (setq num-who (logior #o7000 (default-file-modes))))
              (setq num-modes
                    (file-modes-rights-to-number (substring modes (match-end 1))
                                                 num-who num-modes)
@@ -6884,7 +6864,7 @@ as in \"og+rX-w\"."
 
 (defun read-file-modes (&optional prompt orig-file)
   "Read file modes in octal or symbolic notation and return its numeric value.
-PROMPT is used as the prompt, default to `File modes (octal or symbolic): '.
+PROMPT is used as the prompt, default to \"File modes (octal or symbolic): \".
 ORIG-FILE is the name of a file on whose mode bits to base returned
 permissions if what user types requests to add, remove, or set permissions
 based on existing mode bits, as in \"og+rX-w\"."